1 /*有于需要额外加载easy-x 图形库
2 所以没有装图形库的Vc6.0编译器不能成功编译该代码
3 可以在可执行程序文件夹内
4 找到已经编译好的exe程序和Data.txt(50000学生信息的输入文件)
5 */
6 #include<iostream>
7 #include<cstdio>
8 #include<cstdlib>
9 #include<cstring>
10 #include<ctime>
11 #include<vector>
12 #include<graphics.h>//图形库
13 #include<Windows.h>
14 #include<tchar.h>
15 using namespace std;
16 #define MAXN 2010000 //最大值
17 char inName[100];//读取文件的文件名
18 char outName[100];//输出至文件的文件名
19 int num = 0;
20 int maxdeep = 0;
21 char name[30]={0};
22 typedef int Element;
23 template<class T>
24 struct Node {
25 Node *left_son;//左孩子指针
26 Node *right_son;//右孩子指针
27 T data;//节点储存的信息
28 Node *father;//父亲节点
29 int value;//随机化权值,用于随机数的旋转,保证平衡
30 };
31 template<class T>
32 class Data_tree {//信息类 基于 平衡树-树堆(Treap)实现
33 public:
34 Data_tree() {
35 init();
36 }
37 T* Get_head()//平衡树根指针方法
38 {
39 return head;
40 }
41 void Set_head(T *pt)//更改平衡树指针方法
42 {
43 head = pt;
44 }
45 void init() {
46 head = NULL;//根节点置为空节点
47 size = 0;
48 }
49 void left_turn(T *x) {//节点左旋
50 T* y = x->right_son;//y为节点的右孩子
51 if (y->left_son != NULL) {
52 x->right_son = y->left_son;//y的左孩子设置为x的右孩子
53 y->left_son->father = x;
54 }
55 else
56 x->right_son = NULL;
57 y->father = x->father;//y的父亲设置为x的父亲
58 if (y->father == NULL) {
59 Set_head(y);
60 }
61 else {
62 if (y->father->left_son == x)//如果x是他前父亲的左孩子
63 {
64 y->father->left_son = y;//y就成了他父亲的左孩子
65 }
66 else if (y->father->right_son == x)//如果x是他前父亲的右孩子
67 {
68 y->father->right_son = y;//y就成了他父亲的右孩子
69 }
70 }
71 y->left_son = x;
72 x->father = y;
73 }
74 void right_turn(T *y) {
75 T *x = y->left_son;//x是y的左孩子
76 if (x->right_son != NULL) {
77 y->left_son = x->right_son;//把x的右孩子设置为y的左孩子
78 x->right_son->father = y;//y为x的右孩子的父亲
79 }
80 else
81 y->left_son = NULL;
82 x->father = y->father;//将y的父亲设置为x的父亲
83 if (x->father == NULL) {//如果x没有父亲了
84 Set_head(x);//那么它就是根节点
85 }
86 else {
87 if (x->father->left_son == y) {
88 x->father->left_son = x;
89 }
90 else if (x->father->right_son == y) {
91 x->father->right_son = x;
92 }
93 }
94 x->right_son = y;
95 y->father = x;
96 }
97 void insert(T* &pt) {//插入节点pt
98 int index;//树的性质用决定什么树,以及排序的方式
99 T* newp = Get_newNode();
100 newp->data = pt->data;
101 T* node = Get_head();//获取根节点,以二叉搜索树形式插入
102 size++;
103 if (node == NULL) {//如果是空树
104 Set_head(newp);
105 return;
106 }
107 while (node != NULL) {
108 if (node->data < pt->data)
109 {
110 if (node->right_son == NULL)
111 break;
112 node = node->right_son;//大节点插入右子树
113 }
114 else
115 {
116 if (node->left_son == NULL)//下一个节点为空,跳出循环
117 break;
118 node = node->left_son;//小节点插入左子树
119 }
120 }
121 if (node->data < pt->data) {
122 node->right_son = newp;//插入新节点
123 }
124 else {
125 node->left_son = newp;//插入新节点
126 }
127 newp->father = node;
128 while (node->father != NULL&&node->father->value > node->value) {
129 if (node == node->father->right_son)
130 left_turn(node->father);
131 else if (node == node->father->left_son)
132 right_turn(node->father);
133 }
134 }
135 T* Search(T *pt) {
136 T* node = Get_head();//获取根节点,以二叉搜索树形式查找
137 if (node == NULL) {//如果是空树
138 return 0;
139 }
140 while (node != NULL) {
141 if (node->data == pt->data) {
142 break;
143 }
144 else if (node->data < pt->data)
145 {
146 node = node->right_son;//大节点插入右子树
147 }
148 else
149 {
150 node = node->left_son;//小节点插入左子树
151 }
152 }
153 return node;
154 }
155 bool Erase(T *pt) {
156 T *node = Search(pt);
157 if (node == NULL)//如果没有找到该节点,返回该节点
158 return 0;
159 if (node->father == NULL&&size == 1)//如果是根独苗
160 {
161 Set_head(NULL);//设置为空树
162 size--;
163 return 1;
164 }
165 size--;
166 // cout<<node->right_son<<endl;
167 while (node->left_son != NULL && node->right_son != NULL) {
168 // cout << "???: " << node->data << " " << node->left_son->data << " " << node->right_son->data << endl;
169 if (node->left_son->value<node->right_son->value) {
170 right_turn(node);
171 }
172 else {
173 left_turn(node);
174 }
175 }
176 // cout << "***: " << node << " " << node->left_son << " " << node->right_son << " " << node->father << endl;
177 if (node->left_son != NULL) {//如果还有左孩子
178 if (node->father != NULL)
179 node->left_son->father = node->father;
180 else {
181 Set_head(node->left_son);
182 node->left_son->father = NULL;
183 }
184 if (node->father != NULL) {
185 if (node->father->left_son == node)
186 node->father->left_son = node->left_son;
187 else if (node->father->right_son == node)
188 node->father->right_son = node->left_son;
189 }
190 }
191 else if (node->right_son != NULL) {//如果还有右孩子
192 if (node->father != NULL) {
193
194 node->right_son->father = node->father;
195 }
196 else {
197 Set_head(node->right_son);
198 node->right_son->father = NULL;
199 }
200 if (node->father != NULL) {
201 if (node->father->left_son == node)
202 node->father->left_son = node->right_son;
203 else if (node->father->right_son == node)
204 node->father->right_son = node->right_son;
205 }
206 delete node;
207 }
208 else {//如果没有后代了
209 if (node->father->left_son == node)
210 node->father->left_son = NULL;
211 else if (node->father->right_son == node)
212 node->father->right_son = NULL;
213 delete node;
214 }
215 return 1;
216 }
217 void out(T* pt, int k = 0,FILE *tp=NULL) {//递归前序遍历平衡树
218 if (pt == NULL) return;//空节点不遍历
219 if (pt->left_son != NULL)
220 out(pt->left_son, k,tp);
221 num++;
222 if (k == 1) {
223 printf("%-7d", num);
224 pt->data.out();
225 putchar('\n');
226 }
227 else if(k==2){
228 fprintf(tp,"%-7d", num);
229 pt->data.out(tp);
230 fprintf(tp,"\n");
231 }
232 if (pt->right_son != NULL)
233 out(pt->right_son, k,tp);
234 }
235 void out2(T* pt, int deep) {//递归前序遍历平衡树
236 if (pt == NULL) return;//空节点不遍历
237 printf("%d\n", pt->value);
238 if (deep>maxdeep) maxdeep = deep;
239 if (pt->left_son != NULL)
240 out(pt->left_son, deep + 1);
241 num++;
242 if (pt->right_son != NULL)
243 out(pt->right_son, deep + 1);
244 }
245 void out3(T *pt, vector<int> *a) {
246 if (pt == NULL) return;//空节点不遍历
247 if (pt->left_son != NULL)
248 out3(pt->left_son, a);
249 a->push_back(pt->data.getnumber());
250 if (pt->right_son != NULL)
251 out3(pt->right_son, a);
252 }
253 int size;//平衡树的节点个数
254 private:
255 T* head;//平衡树的根节点指针
256 T *Get_newNode() {//获取一个新声明的初始化节点
257 T* pt;
258 pt = new T();
259 pt->father = NULL;//父亲节点设置为空
260 pt->left_son = NULL;//左右儿子节点置为空
261 pt->right_son = NULL;
262 pt->value = rand();//设置权值为随机数
263 return pt;
264 }
265 };
266 void get_name(int);
267 struct ScoreData {//学生成绩结构体
268 int score;//分数
269 int number;//学号
270 bool operator<(const struct ScoreData &pt)const {
271 if (this->score != pt.score)
272 return this->score>pt.score;
273 else
274 return this->number<pt.number;
275 }
276 bool operator==(const struct ScoreData &pt)const {
277 return this->number == pt.number;
278 }
279 void out(FILE *pt=NULL)//输出成绩
280 {
281 get_name(number);
282 if(pt==NULL)
283 printf("%-7d %-7d %-7s", number, score,name);
284 else
285 fprintf(pt,"%-7d %-7d %-7s",number,score,name);
286 }
287 };
288
289 struct NumberData {//学生学号结构体
290 int number;//学号
291 int score;//分数
292 bool operator<(const struct NumberData &pt)const {
293 return number<pt.number;
294 }
295 bool operator==(const struct NumberData &pt)const {
296 return number == pt.number;
297 }
298 int getnumber() {
299 return number;
300 }
301 };
302
303 struct Student_type {
304 int number;//学号
305 int index;//信息数组下标
306 bool operator<(const Student_type&pt)const {
307 return this->number<pt.number;
308 }
309 bool operator==(const Student_type&pt)const {
310 return this->number == pt.number;
311 }
312 };
313 struct Student {
314 char name[30];
315 int number;//该学生的学号
316 char classnumber[20];
317 char department[20];//该学生的系别编号
318 Student() {
319 name[0] = 0;
320 classnumber[0] = 0;
321 department[0] = 0;
322 }
323 };
324
325 struct ListNode {//信息链表,节点区别为课程名字或系别或班级名字
326 ListNode *next;
327 Data_tree<Node <ScoreData> > tree_score;
328 Data_tree<Node <NumberData> > tree_number;
329 char s[50];
330 int lens;
331 int property;
332 };
333
334 ListNode *Listhead = NULL;//信息链表头
335
336 ListNode* insert_node(char s[], int k = 0) {
337 ListNode *pt = new ListNode();//新生命节点
338 pt->lens = strlen(s);
339 for (int i = 0; i <= pt->lens; i++)/*字符数组s存入新建节点*/
340 pt->s[i] = s[i];
341 pt->next = Listhead;//新节点的下一个为头结点
342 pt->property = k;//设置节点优先级
343 Listhead = pt;
344 return Listhead;//返回该节点指针作为返回值
345 }
346
347
348 ListNode* Search(char s[], int k = 0) {//查找链表
349 ListNode *pt = Listhead;//指针指向链表头部
350 int len = strlen(s);//将字符串s的长度存入len
351 while (pt != NULL) {//循环遍历链表
352 if (pt->lens != len)//如果字符串长度不相同,跳过
353 {
354 pt = pt->next;
355 continue;
356 }
357 else {//否则返回逐一检查字符串中每一个字符
358 int ok = 1;
359 for (int i = 0; i<len; i++)
360 if (s[i] != pt->s[i]) {//如果发现不相等字符,就继续
361 ok = 0;
362 break;
363 }
364 if (ok == 1) {//信息吻合,就返回该节点的指针作为返回值
365 return pt;
366 }
367 }
368 pt = pt->next;
369 }
370 pt = insert_node(s, k);//如果没有找到该节点,那么就新建立一个该属性的节点
371 return pt;//返回新建节点的指针值
372 }
373
374 void insert_data(ListNode* pt, int number, int score) {//向链表的平衡树中插入信息
375 Node<ScoreData> *the_data = new Node<ScoreData>();//插入一个成绩信息,用于该科目核对
376 Node<NumberData> *other_data = new Node<NumberData>();//插入一个学号信息,是否有该学生
377 ScoreData sdata;
378 NumberData odata;
379 odata.number = number;//设置该节点编号
380 other_data->data = odata;
381 other_data = pt->tree_number.Search(other_data);
382 if (other_data != NULL) {//如果该节点非空
383 sdata.number = number;//设置学号
384 sdata.score = other_data->data.score;
385 the_data->data = sdata;
386 pt->tree_score.Erase(the_data);//尝试删除该信息原来的点,以达到覆盖效果
387 }
388 sdata.number = number;//设置节点的学号
389 sdata.score = score;//设置节点的分数
390 the_data->data = sdata;
391 other_data = new Node<NumberData>();
392 pt->tree_score.insert(the_data);//插入该节点
393 odata.score = score;//设置节点的分数
394 odata.number = number;//设置节点的学号
395 other_data->data = odata;
396 pt->tree_number.Erase(other_data);//尝试删除该信息原来的点(如果有的话),以达到覆盖效果
397 pt->tree_number.insert(other_data);//插入该节点
398 }
399
400 void erase_data(ListNode* pt, int number) {//向链表的平衡树中删除信息
401 Node<ScoreData> *the_data = new Node<ScoreData>();//插入一个成绩信息,用于该科目核对
402 ScoreData sdata;
403 sdata.number = number;//设置节点学号
404 the_data->data = sdata;
405 pt->tree_score.Erase(the_data);//尝试删除该信息原来的点(如果有的话),
406 Node<NumberData> *other_data = new Node<NumberData>();//建立一个学号信息
407 NumberData odata;
408 odata.number = number;
409 other_data->data = odata;
410 pt->tree_number.Erase(other_data);//尝试删除该信息原来的点(如果有的话),以达到覆盖效果
411 }
412
413 int getsumscore(int number, int k = 0) {//当k=1时输出该学生各科目信息
414 int sum = 0;//初始化总分数变量
415 ListNode* pt = Listhead;//指针指向链表头部
416 Node<NumberData> *other_data = new Node<NumberData>();
417 NumberData odata;
418 odata.number = number;//设置学号
419 other_data->data = odata;
420 Node<NumberData> *search_data;
421 while (pt != NULL) {//遍历链表
422 if (pt->property != 0) {//如果不是课程节点
423 pt = pt->next;//链表指针指向下一个
424 continue;
425 }
426 search_data = pt->tree_number.Search(other_data);//查找是否能找到有该学号的人
427
428 if (search_data == NULL) {//如果节点为空,那么就跳过
429 pt = pt->next;//链表指针指向下一个
430 continue;
431 }
432 sum += search_data->data.score;//加入成绩至总分
433 if (k != 0)//如果不为0就输出
434 printf("其%s科目的成绩为: %d\n", pt->s, search_data->data.score);
435 pt = pt->next;//链表指针指向下一个
436 }
437 if (k != 0)
438 printf("其总分为: %d\n", sum);
439 return sum;
440 }
441
442 int studentnum = 0;//学生编号表
443 Student studentlist[MAXN];//学生信息表
444 Data_tree<Node <Student_type> > studenttree;
445 int student_insert(int number) {//新插入一个学号的学生
446 //Student_type pt = new Student_type();
447 Node<Student_type> *pt = new Node<Student_type>();
448 pt->data.number = number;
449 pt->data.index = studentnum;
450 studentlist[studentnum].number = number;
451 studenttree.insert(pt);
452 return studentnum++;//返回当前编号
453 }
454
455
456 int get_student_index(int number)//获取该学号在学生数组里的下标
457 {
458 Node<Student_type> *pt = new Node<Student_type>();
459 pt->data.number = number;
460 pt = studenttree.Search(pt);
461 if (pt == NULL)
462 return -1;//失败返回-1
463 else
464 return pt->data.index;//成功返回编号
465 }
466
467 void set_student_name(int number, char s[])//设置该学号学生的名字
468 {
469 int index = get_student_index(number);
470 if (index<0)//若没有该学生信息
471 index = student_insert(number);//插入该学生信息
472 int size = strlen(s);
473 for (int i = 0; i <= size; i++)
474 studentlist[index].name[i] = s[i];//设置学生的名字
475 return;
476 }
477
478 void set_student_classnumber(int number, char s[]) {
479 int index = get_student_index(number);
480 if (index<0)//若没有该学生信息
481 index = student_insert(number);//插入该学生信息
482 int lens = strlen(studentlist[index].classnumber);
483 if (lens > 0)//如果发现有原来班级的信息
484 {
485 ListNode* pt;
486 pt = Search(studentlist[index].classnumber, 1);//找到原来班级的链表节点
487 erase_data(pt, number);//从原来班级删除该学生
488 }
489 int size = strlen(s);
490 for (int i = 0; i <= size; i++)
491 studentlist[index].classnumber[i] = s[i];//设置学生的班级名字
492 return;
493 }
494
495 void get_name(int number) {
496 int index = get_student_index(number);
497 if (index<0)//若没有该学生信息
498 {
499 name[0]='N',name[1]='o',name[2]='t',name[3]=' ',name[4]='s';
500 name[5]='e',name[5]='t',name[5]=' ',name[6]='n';name[7]='a';
501 name[8]='m',name[9]='e',name[10]=0;
502 return;//设置没有名字
503 }
504 int lens = strlen(studentlist[index].name);
505 for(int i=0;i<=lens;i++)
506 name[i]=studentlist[index].name[i];
507 return;
508 }
509
510 void set_student_department(int number, char s[]) {
511 int index = get_student_index(number);
512 if (index<0)//若没有该学生信息
513 index = student_insert(number);//插入该学生信息
514 int lens = strlen(studentlist[index].department);
515 if (lens > 0)//如果发现有原来系别的信息
516 {
517 ListNode* pt;
518 pt = Search(studentlist[index].department, 1);//找到原来系别的链表节点
519 erase_data(pt, number);//从原来系别删除该学生
520 }
521 int size = strlen(s);
522 for (int i = 0; i <= size; i++)
523 studentlist[index].department[i] = s[i];//设置学生的系别名字
524 return;
525 }
526
527
528 void Screen_clear() {//清空屏幕
529 system("cls");
530 }
531
532 int Get_score(char s[], int number) {//获取s课程number学号的成绩
533 ListNode *pt = Search(s);
534 Node<NumberData> *other_data = new Node<NumberData>();
535 NumberData odata;
536 odata.number = number;
537 other_data->data = odata;
538 other_data = pt->tree_number.Search(other_data);
539 if (other_data == NULL)//没有找到该学生
540 return 0;
541 else
542 return other_data->data.score;
543 }
544
545 int Get_score(ListNode *pt, int number) {//获取课程指针pt内number学号学生的成绩
546 if (pt == NULL)
547 return 0;
548 Node<NumberData> *other_data = new Node<NumberData>();
549 NumberData odata;
550 odata.number = number;
551 other_data->data = odata;
552 other_data = pt->tree_number.Search(other_data);
553 if (other_data == NULL)//没有找到该学生
554 return 0;
555 else
556 return other_data->data.score;
557 }
558 void Input_System() {//录入系统
559 Screen_clear();//清屏
560 printf("欢迎您进入学生成绩录入系统\n");
561 printf("本系统采用命令式信息采集方案\n");
562 printf("如果输入之前已设置的信息会覆盖即发生修改\n");
563 printf("命令菜单:\n");
564 printf("命令\t\t\t\t功能\n");
565 printf("%-22s\t\t%s\n", "In data.txt", "读取data.txt全部内容直至文件尾(可自定义文件名)");
566 printf("%-22s\t\t%s\n", "CloseFile", "关闭文件输入方式(需要在文件中输出)");
567 printf("%-22s\t%s\n", "Set Name 1608024101 王XX", "1608024101的学生的名字为王xx");
568 printf("%-22s\t%s\n", "Set Class 1608024101 16080241", "1608024101的学生的班级为16080241");
569 printf("%-22s\t%s\n", "Set Department 1608024101 8院", "1608024101的学生的系别为8院");
570 printf("%-22s\t%s\n", "Set Score 算法 1608024101 0", "将学号为1608024101的算法成绩设置为0分");
571 printf("%-25s\t%s\n", "Exit", "退出当前子系统");
572 printf("现在请您输入相应的指令:\n");
573 FILE *in;//文件读入指针
574 int wj = 0;
575 int start = 0;
576 while (1) {
577 char s[300];
578 if (wj == 0) {
579 scanf("%s", s);//获命令
580 int len = strlen(s);
581 if (len <= 0) {
582 printf("语法错误\n");
583 fflush(stdin);//清空输入缓冲区
584 }
585 if (s[0] == 'I') {
586 scanf("%s", inName);
587 in = fopen(inName, "r");
588 if (in == 0) {
589 printf("打开文件失败,请检查\n");
590 continue;
591 }
592 else {
593 printf("打开文件成功\n");
594 wj = 1;
595 start = clock();
596 continue;
597 }
598 }
599 else if (s[0] == 'C') {
600 wj = 0;
601 in = NULL;
602 int finish = clock();//获取当前时钟
603 printf("读取,并且创建平衡树成功\n共耗时%.6f秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
604 printf("成功将输入源转至键盘\n");
605 continue;
606 }
607 else if (s[0] == 'S') {
608 scanf("%s", s);
609 if (s[0] == 'N') {
610 char name[300];
611 int number;
612 scanf("%d", &number);
613 scanf("%s", name);
614 set_student_name(number, name);
615 printf("设置名字成功\n");
616 }
617 else if (s[0] == 'C') {
618 char classes[300];
619 int number;
620 scanf("%d", &number);
621 scanf("%s", classes);
622 set_student_classnumber(number, classes);
623 ListNode *pt;
624 pt = Search(classes, 1);
625 insert_data(pt, number, 1);
626 printf("设置班级成功\n");
627 }
628 else if (s[0] == 'D') {
629 char department[300];
630 int number;
631 scanf("%d", &number);
632 scanf("%s", department);
633 set_student_department(number, department);
634 ListNode *pt;
635 pt = Search(department, 1);
636 insert_data(pt, number, 1);
637 printf("设置系别成功\n");
638 }
639 else if (s[0] == 'S') {
640 int number;
641 char coursename[30];
642 int score;
643 scanf("%s", coursename);
644 scanf("%d%d", &number, &score);
645 int index = get_student_index(number);
646 if (index<0)//若没有该学生信息
647 index = student_insert(number);//插入该学生信息
648 ListNode *pt;
649 pt = Search(coursename);
650 insert_data(pt, number, score);
651 printf("设置成绩成功\n");
652 }
653 else {
654 printf("语法错误\n");
655 fflush(stdin);//清空输入缓冲区
656 }
657 }
658 else if (s[0] == 'E') {
659 printf("即将在2秒后退出\n");
660 Sleep(2000);
661 return;
662 }
663 else {
664 printf("语法错误\n");
665 fflush(stdin);//清空输入缓冲区
666 }
667 }
668 else {
669 if(fscanf(in, "%s", s)==EOF){
670 s[0]='C';
671 s[1]=0;//没有文件,设置结束
672 };//获命令
673 int len = strlen(s);
674 if (len <= 0) {
675 }
676 else if (s[0] == 'C') {
677 wj = 0;
678 in = NULL;
679 int finish = clock();//获取当前时钟
680 printf("读取,并且创建平衡树成功\n共耗时%.6f秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
681 printf("成功将输入源转至键盘\n");
682 continue;
683 }
684 else if (s[0] == 'S') {
685 fscanf(in, "%s", s);
686 if (s[0] == 'N') {
687 char name[300];
688 int number;
689 fscanf(in, "%d", &number);
690 fscanf(in, "%s", name);
691 set_student_name(number, name);
692 }
693 else if (s[0] == 'C') {
694 char classes[300];
695 int number;
696 fscanf(in, "%d", &number);
697 fscanf(in, "%s", classes);
698 set_student_classnumber(number, classes);
699 ListNode *pt;
700 pt = Search(classes, 1);
701 insert_data(pt, number, 1);
702 }
703 else if (s[0] == 'D') {
704 char department[300];
705 int number;
706 fscanf(in, "%d", &number);
707 fscanf(in, "%s", department);
708 set_student_department(number, department);
709 ListNode *pt;
710 pt = Search(department, 1);
711 insert_data(pt, number, 1);
712 }
713 else if (s[0] == 'S') {
714 int number;
715 char coursename[30];
716 int score;
717 fscanf(in, "%s", coursename);
718 fscanf(in, "%d%d", &number, &score);
719 int index = get_student_index(number);
720 if (index<0)//若没有该学生信息
721 index = student_insert(number);//插入该学生信息
722 ListNode *pt;
723 pt = Search(coursename);
724 insert_data(pt, number, score);
725 }
726 }
727 }
728 }
729 }
730
731 vector<int> num_vector;
732 ScoreData* Score_vector;
733
734 void Output_System() {//输出系统
735 Screen_clear();//清屏
736 printf("欢迎您进入信息输出系统\n");
737 printf("本系统采用命令式交互方案\n");
738 printf("命令菜单:\n");
739 printf("命令\t\t\t\t\t功能\n");
740 printf("%-22s\t\t%s\n", "Query Number 1608024101", "输出1608024101的各科目成绩");
741 printf("%-22s\t\t%s\n", "Query Data 1608024101", "输出1608024101的信息");
742 printf("%-22s\t\t%s\n", "Query Course 数学分析", "输出数学分析科目的所有的成绩");
743 printf("%-22s\t\t%s\n", "Query Department 8院", "输出8院的所有同学的学号");
744 printf("%-22s\t\t%s\n", "Query Class 16080241", "输出16080241班的所有同学的学号");
745 printf("%-25s\t\t%s\n", "Exit", "退出当前子系统");
746 printf("现在请您输入相应的指令:\n");
747 while (1) {
748 char s[300];
749 num = 0;
750 scanf("%s", s);//获命令
751 int len = strlen(s);
752 if (len <= 1) {
753 printf("语法错误\n");
754 fflush(stdin);//清空输入缓冲区
755 continue;
756 }
757 if (s[0] == 'Q') {
758 scanf("%s", s);
759 if (strlen(s) < 3) {
760 printf("语法错误\n");
761 fflush(stdin);//清空输入缓冲区
762 continue;
763 }
764 if (s[0] == 'N'&&s[1] == 'u') {
765 char name[300];
766 int number;
767 scanf("%d", &number);
768 getsumscore(number, 1);
769 printf("查找该学生成绩成功\n");
770 }
771 else if (s[0] == 'D'&&s[1] == 'a') {
772 char name[300];
773 int number;
774 scanf("%d", &number);
775 int index = get_student_index(number);
776 if (index < 0)//没有该生信息
777 {
778 printf("对不起,并没有找到该学号的学生\n");
779 continue;
780 }
781 else if (index >= 0) {
782 printf("学号:%d\n", number);
783 if (strlen(studentlist[index].name) > 0)
784 printf("姓名:%s\n", studentlist[index].name);
785 else
786 printf("姓名:尚未定义\n");
787 if (strlen(studentlist[index].classnumber) > 0)
788 printf("班级:%s\n", studentlist[index].classnumber);
789 else
790 printf("班级:尚未定义\n");
791 if (strlen(studentlist[index].department) > 0)
792 printf("系别:%s\n", studentlist[index].department);
793 else
794 printf("系别:尚未定义\n");
795 }
796 printf("查找该学生信息成功\n");
797 continue;
798 }
799 else if (s[0] == 'C'&&s[1] == 'o') {
800 char classes[300];
801 scanf("%s", classes);
802 ListNode* pt;
803 pt = Search(classes);
804 printf("%7s %7s %7s %7s\n", "名次", "学号", "成绩","姓名");
805 pt->tree_score.out(pt->tree_score.Get_head(), 1);
806 }
807 else if (s[0] == 'D') {
808 char department[300];
809 scanf("%s", department);
810 ListNode* pt;
811 pt = Search(department);
812 printf("%7s %7s\n", "序号", "学号");
813 num_vector.clear();
814 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
815 int i;
816 for (i = 0; i < num_vector.size(); i++) {
817 printf("%-7d%-7d\n", i + 1, num_vector[i]);
818 }
819 }
820 else if (s[0] == 'C'&&s[1] == 'l') {
821 char classes[300];
822 scanf("%s", classes);
823 ListNode* pt;
824 pt = Search(classes);
825 printf("%7s %7s\n", "序号", "学号");
826 num_vector.clear();
827 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
828 int i;
829 for (i = 0; i < num_vector.size(); i++) {
830 printf("%7d %7d\n", i + 1, num_vector[i]);
831 }
832 }
833 else {
834 printf("语法错误\n");
835 fflush(stdin);//清空输入缓冲区
836 }
837 }
838 else if (s[0] == 'E') {
839 printf("即将在2秒后退出\n");
840 Sleep(2000);
841 return;
842 }
843 else {
844 printf("语法错误\n");
845 fflush(stdin);//清空输入缓冲区
846 }
847 }
848 }
849
850 void swap(ScoreData *p, ScoreData *q) { //交换两个变量的值
851 ScoreData t = *q;
852 *q = *p; *p = t;
853 }
854
855 void Quicksort(ScoreData a[], int l, int r) {//快速排序
856 if (l >= r) return;//区间内小于等于1个元素的时候,不用排序,直接返回
857 int t = rand() % (r - l + 1) + l; //t为基准值位置,这里采用随机选取
858 swap(&a[l], &a[t]);
859 int i = l, j = r;
860 ScoreData mid = a[l];
861 while (i<j) {
862 while (i < j&&mid < a[j]) j--; //将比基准值小的元素放在基准值左边
863 a[i] = a[j];
864 while (i < j && !(mid < a[i])) i++; //将比基准值大的元素放在基准值右边
865 a[j] = a[i];
866 }
867 a[i] = mid;//基准值放在中间
868 Quicksort(a, l, i - 1);//递归排序基准值左边
869 Quicksort(a, i + 1, r);//递归排序基准值右边
870 }
871
872 int pass_score = 60, good_score = 90;//及格线,优秀线
873 void analy(ScoreData a[], int n) {
874 int passnum = 0, goodnum = 0;//及格人数,优秀人数
875 for (int i = 0; i < n; i++) {
876 if (a[i].score >= pass_score)
877 passnum++;
878 if (a[i].score >= good_score)
879 goodnum++;
880 }
881 printf("总人数: %d\n", n);
882 printf("及格人数: %d\n", passnum);
883 printf("及格率: %.2f\n", (double)passnum / n);
884 printf("优秀人数: %d\n", goodnum);
885 printf("优秀率: %.2f\n", (double)goodnum / n);
886 }
887
888 void analy2(ScoreData a[], int n) {
889 int minn = 0x3f3f3f3f, maxn = 0;//及格人数,优秀人数
890 int ans = 0;
891 for (int i = 0; i < n; i++) {
892 if (a[i].score > maxn)
893 maxn = a[i].score;
894 if (a[i].score < minn)
895 minn = a[i].score;
896 ans += a[i].score;
897 }
898 printf("总人数: %d\n", n);
899 printf("最高分数: %d\n", maxn);
900 printf("最低分数: %d\n", minn);
901 printf("平均成绩: %.2f\n", (double)ans / n);
902 }
903
904 void Analyze_System() {
905 Screen_clear();//清除屏幕
906 printf("欢迎您进入成绩分析系统\n");
907 printf("本系统采用命令式交互方案\n");
908 printf("命令菜单:\n");
909 printf("命令\t\t\t\t\t功能\n");
910 printf("%-22s\t\t%s\n", "Analyze Class 16080241 数学分析", "输出16080241班的数学分析的成绩分析");
911 printf("%-22s\t%s\n", "Analyze Department 数学系 数学分析", "输出数学系班的数学分析的成绩分析");
912 printf("%-22s\t\t\t%s\n", "Set Goodline 95", "设置优秀线95 默认是90分");
913 printf("%-22s\t\t\t%s\n", "Set Passline 50", "设置及格线50 默认是60分");
914 printf("%-25s\t\t%s\n", "Exit", "退出当前子系统");
915 printf("现在请您输入相应的指令:\n");
916 while (1) {
917 char s[300];
918 scanf("%s", s);
919 if (s[0] == 'A') {
920 scanf("%s", s);
921 if (strlen(s) < 1) {
922 printf("语法错误\n");
923 continue;
924 }
925 else if (s[0] == 'C') {
926 char classes[300];
927 scanf("%s", classes);
928 ListNode* pt;
929 pt = Search(classes);
930 num_vector.clear();
931 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
932 if (num_vector.size() == 0) {
933 printf("该列表没有成员\n");
934 continue;
935 }
936 int i;
937 char name[300];
938 scanf("%s", name);
939 pt = Search(name, 1);//获取该课程指针
940 Score_vector = new ScoreData[num_vector.size()];//创立一个该班人数大小的线性表
941 for (i = 0; i < num_vector.size(); i++) {
942 Score_vector[i].number = num_vector[i];//存储学号
943 Score_vector[i].score = Get_score(pt, Score_vector[i].number);
944 }
945 analy(Score_vector, num_vector.size());
946 }
947 else if (s[0] == 'D') {
948 char department[300];
949 scanf("%s", department);
950 ListNode* pt;
951 pt = Search(department);
952 //printf("%7s %7s\n", "序号", "学号");
953 num_vector.clear();
954 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
955 char name[300];
956 scanf("%s", name);
957 if (num_vector.size() == 0) {
958 printf("该列表没有成员\n");
959 continue;
960 }
961 pt = Search(name, 1);//获取该课程指针
962 int i;
963 Score_vector = new ScoreData[num_vector.size()];//创立一个该系人数大小的线性表
964 for (i = 0; i < num_vector.size(); i++) {
965 Score_vector[i].number = num_vector[i];//存储学号
966 Score_vector[i].score = Get_score(pt, Score_vector[i].number);
967 }
968 analy(Score_vector, num_vector.size());
969 }
970 else {
971 printf("语法错误\n");
972 continue;
973 }
974 }
975 else if (s[0] == 'S') {
976 int d;
977 scanf("%s", s);
978 scanf("%d", &d);
979 if (s[0] == 'G') {
980 good_score = d;//设置优秀线
981 printf("设置成功\n");
982 }
983 else if (s[0] == 'P') {
984 pass_score = d;//设置及格线
985 printf("设置成功\n");
986 }
987 }
988 else if (s[0] == 'E') {
989 return;
990 }
991 }
992 }
993
994 void Course_System() {
995 Screen_clear();//清除屏幕
996 printf("欢迎您进入课程成绩分析系统\n");
997 printf("请输出操作指令:\n");
998 printf("1.分析课程\n");
999 printf("2.退出\n");
1000 while (1) {
1001 int c = getchar();
1002 while (!(c > '0'&&c <= '2')) {
1003 c = getchar();
1004 continue;
1005 }
1006 if (c == '1') {
1007 printf("请输入分析的课程名字:\n");
1008 char name[300];
1009 scanf("%s", name);
1010 ListNode* pt;
1011 pt = Search(name);
1012 num_vector.clear();
1013 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1014 if (num_vector.size() == 0) {
1015 printf("该列表没有成员\n");
1016 continue;
1017 }
1018 int i;
1019 Score_vector = new ScoreData[num_vector.size()];//创立一个该课程人数大小的线性表
1020 for (i = 0; i < num_vector.size(); i++) {
1021 Score_vector[i].number = num_vector[i];//存储学号
1022 Score_vector[i].score = Get_score(pt, Score_vector[i].number);
1023 }
1024 analy2(Score_vector, num_vector.size());
1025 }
1026 else if (c == '2')
1027 return;
1028 }
1029 }
1030
1031 void Rank_System() {//排名系统
1032 Screen_clear();//清除屏幕
1033 printf("欢迎您进入成绩排名系统\n");
1034 printf("本系统采用命令式交互方案\n");
1035 printf("命令菜单:\n");
1036 printf("命令\t\t\t\t\t功能\n");
1037 printf("%-22s\t\t\t%s\n", "Out to data.txt", "将排名输出至 data.txt 可以自定义文件名");
1038 printf("%-22s\t\t\t%s\n", "Out Recover", "将排名重新输出至屏幕");
1039 printf("%-22s\t\t%s\n", "Rank Class 16080241 数学分析", "输出16080241班的数学分析的成绩排名");
1040 printf("%-22s\t\t%s\n", "Rank Department 数学系 数学分析", "输出数学系的数学分析的成绩排名");
1041 printf("%-22s\t\t\t%s\n", "Rank AllClass 16080241", "输出16080241班的数学分析的成绩排名");
1042 printf("%-22s\t\t%s\n", "Rank AllDepartment 数学系", "输出数学系的总成绩的成绩排名");
1043 printf("%-25s\t\t%s\n", "Exit", "退出当前子系统");
1044 printf("现在请您输入相应的指令:\n");
1045 int i;
1046 int wj = 0;//是否进行文件输出
1047 FILE* filepoint;
1048 while (1) {
1049 char s[300];
1050 scanf("%s", s);
1051 if (s[0] == 'O') {
1052 scanf("%s", outName);
1053 if (outName[0] == 't') {
1054 scanf("%s", outName);
1055 filepoint = fopen(outName, "w+");
1056 if (filepoint == NULL) {
1057 printf("输出转向文件失败!\n");
1058 continue;
1059 }
1060 else {
1061 printf("输出转向文件成功\n");
1062 wj = 1;
1063 continue;
1064 }
1065 }
1066 else {
1067 if (outName[0] == 'R' || outName[0] == 'r') {
1068 fclose(filepoint);
1069 filepoint = NULL;
1070 wj = 0;
1071 printf("输出转至屏幕成功\n");
1072 continue;
1073 }
1074 }
1075 }
1076 else if (s[0] == 'R') {
1077 scanf("%s", s);
1078 if (s[0] == 'C') {
1079 char classes[300];
1080 scanf("%s", classes);
1081 ListNode* pt;
1082 pt = Search(classes);
1083 num_vector.clear();
1084 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1085 scanf("%s", classes);
1086 if (num_vector.size() == 0) {
1087 printf("该列表没有成员\n");
1088 continue;
1089 }
1090 pt = Search(classes, 1);//获取该课程指针
1091 Score_vector = new ScoreData[num_vector.size()];//创立一个该班人数大小的线性表
1092 for (i = 0; i < num_vector.size(); i++) {
1093 //printf("%7d %7d\n", i + 1, num_vector[i]);
1094 Score_vector[i].number = num_vector[i];//存储学号
1095 Score_vector[i].score = Get_score(pt, Score_vector[i].number);
1096 }
1097 Quicksort(Score_vector, 0, num_vector.size() - 1);
1098 if (wj == 0)
1099 printf("%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1100 else
1101 fprintf(filepoint, "%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1102 int i;
1103 int start = clock();
1104 for (i = 0; i <= num_vector.size() - 1; i++) {
1105 get_name(Score_vector[i].number);
1106 if (wj == 0)
1107 printf("%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1108 else
1109 fprintf(filepoint, "%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1110 }
1111 int finish = clock();
1112 if (wj == 1) {
1113 printf("输出至文件成功,所用时间: %.6f 秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
1114 }
1115 }
1116 else if (s[0] == 'D') {
1117 char department[300];
1118 scanf("%s", department);
1119 ListNode* pt;
1120 pt = Search(department);
1121 num_vector.clear();
1122 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1123 scanf("%s", department);
1124 if (num_vector.size() == 0) {
1125 printf("该列表没有成员\n");
1126 continue;
1127 }
1128 pt = Search(department, 1);//获取该课程指针
1129 Score_vector = new ScoreData[num_vector.size()];//创立一个该系别人数大小的线性表
1130 for (i = 0; i < num_vector.size(); i++) {
1131 Score_vector[i].number = num_vector[i];//存储学号
1132 Score_vector[i].score = Get_score(pt, Score_vector[i].number);
1133 }
1134 Quicksort(Score_vector, 0, num_vector.size() - 1);
1135 if (wj == 0)
1136 printf("%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1137 else
1138 fprintf(filepoint, "%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1139 int start = clock();
1140 for (i = 0; i <= num_vector.size() - 1; i++) {
1141 get_name(Score_vector[i].number);
1142 if (wj == 0)
1143 printf("%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1144 else
1145 fprintf(filepoint, "%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1146 }
1147 int finish = clock();
1148 if (wj == 1) {
1149 printf("输出至文件成功,所用时间: %.6f 秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
1150 }
1151 }
1152 else if (s[0] == 'A'&&strlen(s) > 4 && s[3] == 'C') {
1153 char classes[300];
1154 scanf("%s", classes);
1155 ListNode* pt;
1156 pt = Search(classes);
1157 num_vector.clear();
1158 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1159 if (num_vector.size() == 0) {
1160 printf("该列表没有成员\n");
1161 continue;
1162 }
1163 Score_vector = new ScoreData[num_vector.size()];//创立一个该班人数大小的线性表
1164 for (i = 0; i < num_vector.size(); i++) {
1165 Score_vector[i].number = num_vector[i];//存储学号
1166 Score_vector[i].score = getsumscore(Score_vector[i].number);
1167 }
1168 Quicksort(Score_vector, 0, num_vector.size() - 1);
1169 if (wj == 0)
1170 printf("%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1171 else
1172 fprintf(filepoint, "%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1173 int i;
1174 int start = clock();
1175 for (i = 0; i <= num_vector.size() - 1; i++) {
1176 get_name(Score_vector[i].number);
1177 if (wj == 0)
1178 printf("%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1179 else
1180 fprintf(filepoint, "%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1181 }
1182 int finish = clock();
1183 if (wj == 1) {
1184 printf("输出至文件成功,所用时间: %.6f 秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
1185 }
1186 }
1187 else if (s[0] == 'A'&&strlen(s) > 4 && s[3] == 'D') {
1188 char department[300];
1189 scanf("%s", department);
1190 ListNode* pt;
1191 pt = Search(department);
1192 num_vector.clear();
1193 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1194 int i;
1195 if (num_vector.size() == 0) {
1196 printf("该列表没有成员\n");
1197 continue;
1198 }
1199 Score_vector = new ScoreData[num_vector.size()];//创立一个该系别人数大小的线性表
1200 for (i = 0; i < num_vector.size(); i++) {
1201 Score_vector[i].number = num_vector[i];//存储学号
1202 Score_vector[i].score = getsumscore(Score_vector[i].number);
1203 }
1204 Quicksort(Score_vector, 0, num_vector.size() - 1);
1205 if (wj == 0)
1206 printf("%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1207 else
1208 fprintf(filepoint, "%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1209 int start = clock();
1210 for (i = 0; i <= num_vector.size() - 1; i++) {
1211 get_name(Score_vector[i].number);
1212 if (wj == 0)
1213 printf("%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1214 else
1215 fprintf(filepoint, "%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1216 }
1217 int finish = clock();
1218 if (wj == 1) {
1219 printf("输出至文件成功,所用时间: %.6f 秒\n", (double)(finish - start) / CLOCKS_PER_SEC);
1220 }
1221 }
1222 else {
1223 if (wj == 0)
1224 printf("语法错误\n");
1225 continue;
1226 }
1227 }
1228 else if (s[0] == 'E') {
1229 return;
1230 }
1231 }
1232 }
1233 const int X = 800, Y = 600;//画面宽度与高度
1234
1235 int getmouse() {
1236 MOUSEMSG mouse_message;//鼠标消息变量
1237 while (1) {
1238 if (MouseHit()) {//如果有鼠标消息,进入if
1239 mouse_message = GetMouseMsg();//获取当前的鼠标消息
1240 if (mouse_message.uMsg == WM_LBUTTONDOWN)//如果鼠标左键按下
1241 {
1242 int x = mouse_message.x;
1243 int y = mouse_message.y;//获取鼠标当前所在的坐标
1244 /*检查鼠标位置*/
1245 if (x >= 100 && y >= 20 && x <= 300 && y <= 140)
1246 return 1;//退出鼠标检测函数,进入下一项
1247 else if (x >= 500 && y >= 20 && x <= 700 && y <= 140)
1248 return 2;//退出鼠标检测函数,进入下一项
1249 else if (x >= 100 && y >= 250 && x <= 300 && y <= 370)
1250 return 3;//退出鼠标检测函数,进入下一项
1251 else if (x >= 500 && y >= 250 && x <= 700 && y <= 370)
1252 return 4;
1253 }
1254 FlushMouseMsgBuffer();//清空鼠标消息,以避免消息冲突
1255 }
1256 }
1257 }
1258
1259 void Message(char *s1, char *s2) {//提示框
1260 HWND hwnd = GetHWnd();//获取窗口句柄
1261 MessageBox(hwnd, s1, s2, 0);//输出相关内容
1262 }
1263 char s[1000];
1264 void openfile()//图形化文件读取
1265 {
1266 const int Max_PATH = 100;
1267 TCHAR szBuffer[Max_PATH] = { 0 }; //保存文件名
1268 HWND m_hWnd = GetHWnd();//获取窗口句柄
1269 OPENFILENAME ofn = { 0 };
1270 ofn.lStructSize = sizeof(ofn);
1271 ofn.hwndOwner = m_hWnd;
1272 ofn.lpstrFilter = _T("TxT文件(*.txt)*.txt所有文件(*.*)*.*");//要选择的文件后缀
1273 ofn.lpstrInitialDir = _T("C:\\Users\\Administrator\\Desktop\\");//默认的文件路径
1274 ofn.lpstrFile = szBuffer;//存放文件的缓冲区
1275 ofn.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
1276 ofn.nFilterIndex = 0;
1277 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;//标志如果是多选要加上OFN_ALLOWMULTISELECT
1278 BOOL bSel = GetOpenFileName(&ofn);
1279 if (bSel == false) {
1280 Message("请检查文件输入", "请检查文件输入");
1281 return;
1282 }
1283 FILE* in = NULL;
1284 in = fopen(szBuffer, "r");//只读方式打开文件
1285 if (in == NULL) {//文件打开失败
1286 Message("请检查文件是否存在", "请检查文件是否存在");
1287 return;
1288 }
1289 while (1) {//读取文件
1290 if(fscanf(in, "%s", s)==EOF)
1291 s[0]='C',s[1]=0;
1292 int len = strlen(s);
1293 if (len <= 0) {
1294 }
1295 else if (s[0] == 'C') {
1296 fclose(in);
1297 in = NULL;
1298 int finish = clock();//获取当前时钟
1299 Message("读取成功", "成功");
1300 return;
1301 }
1302 else if (s[0] == 'S') {
1303 fscanf(in, "%s", s);
1304 if (s[0] == 'N') {
1305 char name[300];
1306 int number;
1307 fscanf(in, "%d", &number);
1308 fscanf(in, "%s", name);
1309 set_student_name(number, name);
1310 }
1311 else if (s[0] == 'C') {
1312 char classes[300];
1313 int number;
1314 fscanf(in, "%d", &number);
1315 fscanf(in, "%s", classes);
1316 set_student_classnumber(number, classes);
1317 ListNode *pt;
1318 pt = Search(classes, 1);
1319 insert_data(pt, number, 1);
1320 }
1321 else if (s[0] == 'D') {
1322 char department[300];
1323 int number;
1324 fscanf(in, "%d", &number);
1325 fscanf(in, "%s", department);
1326 set_student_department(number, department);
1327 ListNode *pt;
1328 pt = Search(department, 1);
1329 insert_data(pt, number, 1);
1330 }
1331 else if (s[0] == 'S') {
1332 int number;
1333 char coursename[30];
1334 int score;
1335 fscanf(in, "%s", coursename);
1336 fscanf(in, "%d%d", &number, &score);
1337 int index = get_student_index(number);
1338 if (index<0)//若没有该学生信息
1339 index = student_insert(number);//插入该学生信息
1340 ListNode *pt;
1341 pt = Search(coursename);
1342 insert_data(pt, number, score);
1343 }
1344 }
1345 }
1346 }
1347
1348 void Save_course(){//保存课程
1349 const int Max_PATH = 100;
1350 TCHAR szBuffer[Max_PATH] = { 0 }; //保存文件名
1351 HWND m_hWnd = GetHWnd();//获取窗口句柄
1352 OPENFILENAME ofn = { 0 };
1353 ofn.lStructSize = sizeof(ofn);
1354 ofn.hwndOwner = m_hWnd;
1355 ofn.lpstrFilter = _T("TxT文件(*.txt)*.txt所有文件(*.*)*.*");//要选择的文件后缀
1356 ofn.lpstrInitialDir = _T("C:\\Users\\Administrator\\Desktop\\");//默认的文件路径
1357 ofn.lpstrFile = szBuffer;//存放文件的缓冲区
1358 ofn.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
1359 ofn.nFilterIndex = 0;
1360 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;//标志如果是多选要加上OFN_ALLOWMULTISELECT
1361 BOOL bSel = GetOpenFileName(&ofn);
1362 if (bSel == false) {
1363 Message("请检查文件输入", "请检查文件输入");
1364 return;
1365 }
1366 FILE* out = NULL;
1367 out = fopen(szBuffer, "w+");//写入方式打开文件
1368 if (out == NULL) {//文件打开失败
1369 Message("请检查文件是否存在", "请检查文件是否存在");
1370 return;
1371 }
1372 char classes[300];
1373 InputBox(classes,250,"请输入要查询的课程名称","请输入",NULL,0,0,true);//弹出提示输入框 读取用户输入
1374 ListNode* pt;
1375 pt = Search(classes);
1376 fprintf(out,"%7s %7s %7s %7s\n", "名次", "学号", "成绩","名字");
1377 pt->tree_score.out(pt->tree_score.Get_head(), 2,out);
1378 fclose(out);
1379 Message("输出成功", "成功");
1380 }
1381
1382 void save_class(){//输出课程信息至文件
1383 const int Max_PATH = 100;
1384 TCHAR szBuffer[Max_PATH] = { 0 }; //保存文件名
1385 HWND m_hWnd = GetHWnd();//获取窗口句柄
1386 OPENFILENAME ofn = { 0 };
1387 ofn.lStructSize = sizeof(ofn);
1388 ofn.hwndOwner = m_hWnd;
1389 ofn.lpstrFilter = _T("TxT文件(*.txt)*.txt所有文件(*.*)*.*");//要选择的文件后缀
1390 ofn.lpstrInitialDir = _T("C:\\Users\\Administrator\\Desktop\\");//默认的文件路径
1391 ofn.lpstrFile = szBuffer;//存放文件的缓冲区
1392 ofn.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
1393 ofn.nFilterIndex = 0;
1394 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;//标志如果是多选要加上OFN_ALLOWMULTISELECT
1395 BOOL bSel = GetOpenFileName(&ofn);
1396 if (bSel == false) {
1397 Message("请检查文件输入", "请检查文件输入");
1398 return;
1399 }
1400 FILE* out = NULL;
1401 out = fopen(szBuffer, "w+");//写入方式打开文件
1402 if (out == NULL) {//文件打开失败
1403 Message("请检查文件是否存在", "请检查文件是否存在");
1404 return;
1405 }
1406 char classes[300];
1407 InputBox(classes,250,"请输入要查询的班级或系别名称","请输入",NULL,0,0,true);//弹出提示输入框 读取用户输入
1408 ListNode* pt;
1409 pt = Search(classes);
1410 num_vector.clear();
1411 pt->tree_number.out3(pt->tree_number.Get_head(), &num_vector);
1412 if (num_vector.size() == 0) {
1413 fprintf(out,"该列表没有成员\n");
1414 fclose(out);
1415 return;
1416 }
1417 Score_vector = new ScoreData[num_vector.size()];//创立一个该班人数大小的线性表
1418 int i;
1419 for (i = 0; i < num_vector.size(); i++) {
1420 Score_vector[i].number = num_vector[i];//存储学号
1421 Score_vector[i].score = getsumscore(Score_vector[i].number);
1422 }
1423 Quicksort(Score_vector, 0, num_vector.size() - 1);
1424 fprintf(out, "%7s %7s %7s %7s\n", "排名", "学号", "分数","名字");
1425 for (i = 0; i <= num_vector.size() - 1; i++) {
1426 get_name(Score_vector[i].number);
1427 fprintf(out, "%7d %7d %7d %7s\n", i + 1, Score_vector[i].number, Score_vector[i].score,name);
1428 }
1429 Message("输出成功","输出成功");
1430 fclose(out);
1431 }
1432 void exit(){
1433 closegraph();// 关闭绘图窗口
1434 }
1435 void deal() {
1436 while (1) {
1437 int p = getmouse();
1438 if (p == 1) {
1439 openfile();
1440 }
1441 else if (p == 2) {
1442 Save_course();
1443 }
1444 else if (p == 3) {
1445 save_class();
1446 }
1447 else if (p == 4) {
1448 exit();
1449 return;
1450 }
1451 }
1452 }
1453
1454 void grap()//图形化界面
1455 {
1456 initgraph(X, Y);//创立界面
1457 HWND hwnd = GetHWnd();//获取窗口句柄
1458 SetWindowText(hwnd, "学生成绩管理系统图形化操作界面 BY:WYS");
1459 IMAGE img1;//初始窗口背景
1460 loadimage(&img1, _T("Main_g.jpg"), X, Y, true);
1461 putimage(0, 0, &img1, SRCCOPY);//在窗口上绘制背景图片 第三个参数为 绘制出的像素颜色=原图形颜色
1462 IMAGE img2, img2f;//保存窗口按钮
1463 loadimage(&img1, _T("Main_g.jpg"), X, Y, true);
1464 putimage(0, 0, &img1, SRCCOPY);//在窗口上绘制背景图片 第三个参数为 绘制出的像素颜色=原图形颜色
1465
1466 loadimage(&img2f, _T("Opy.jpg"), X / 4, Y / 5, true);//加载标题图片-掩码
1467 putimage(100, 20, &img2f, NOTSRCERASE);//打印标题图片-掩码
1468 loadimage(&img2, _T("Op.jpg"), X / 4, Y / 5, true);//加载标题图片
1469 putimage(100, 20, &img2, SRCINVERT);//打印标题图片
1470
1471 loadimage(&img2f, _T("bcky.jpg"), X / 4, Y / 5, true);//加载标题图片-掩码
1472 putimage(500, 20, &img2f, NOTSRCERASE);//打印标题图片-掩码
1473 loadimage(&img2, _T("bck.jpg"), X / 4, Y / 5, true);//加载标题图片
1474 putimage(500, 20, &img2, SRCINVERT);//打印标题图片
1475
1476 loadimage(&img2f, _T("bcby.jpg"), X / 4, Y / 5, true);//加载标题图片-掩码
1477 putimage(100, 250, &img2f, NOTSRCERASE);//打印标题图片-掩码
1478 loadimage(&img2, _T("bcb.jpg"), X / 4, Y / 5, true);//加载标题图片
1479 putimage(100, 250, &img2, SRCINVERT);//打印标题图片
1480
1481 loadimage(&img2f, _T("exitf.jpg"), X / 4, Y / 5, true);//加载标题图片-掩码
1482 putimage(500, 250, &img2f, NOTSRCERASE);//打印标题图片-掩码
1483 loadimage(&img2, _T("exit.jpg"), X / 4, Y / 5, true);//加载标题图片
1484 putimage(500, 250, &img2, SRCINVERT);//打印标题图片
1485 deal();//处理
1486 }
1487
1488 void Main_menu() {//主菜单
1489 while (1) {
1490 Screen_clear();//清屏
1491 printf("\t\t欢迎使用学生成绩管理系统\n");
1492 printf("\t\t\t请输入操作命令\n");
1493 printf("\t\t\t1.录入/修改系统\n");
1494 printf("\t\t\t2.查询系统\n");
1495 printf("\t\t\t3.班/系 成绩分析系统\n");
1496 printf("\t\t\t4.课程成绩分析系统\n");
1497 printf("\t\t\t5.排名系统\n");
1498 printf("\t\t\t6.退出程序\n");
1499 printf("\t\t\t7.拓展功能:图形化操作模式\n");
1500 printf("\t\t\t请您输入操作指令\n");
1501 printf("\t\t\t");
1502 char s;
1503 s = getchar();
1504 if (!(s <= '7'&&s >= '1')) {//检查输入命令
1505 fflush(stdin);//清空输入缓冲区
1506 continue;
1507 }
1508 int order = s - '0';//获取命令编号
1509 if (order == 1)
1510 Input_System();
1511 else if (order == 2)
1512 Output_System();
1513 else if (order == 3)
1514 Analyze_System();
1515 else if (order == 4)
1516 Course_System();
1517 else if (order == 5)
1518 Rank_System();
1519 else if (order == 6)
1520 exit(0);
1521 else if (order == 7)
1522 grap();
1523 }
1524 }
1525
1526 int main() {
1527 srand(time(0));
1528 Main_menu();
1529 return 0;
1530 }