学生管理系统管理系统
本系统是大一课程设计中课程设计做出来的!
-----------------完成时间2013 06 08
1 /学生管理系统 完成时间2013 06 08 2 //大一第一次课程设计 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #define N 3 7 #define LEN (Student*) malloc(sizeof(Student)) 8 /* 学生数据结构 */ 9 typedef struct node 10 { 11 char num[20]; 12 char name[15]; 13 int score[N]; 14 int sum; 15 double ave; 16 struct node *next; 17 } Student; 18 19 /* 头指针 */ 20 Student *head = NULL; 21 /* 临时指针 */ 22 Student *tmp = NULL; 23 /* 课程名称 */ 24 char CLASSNAME[N][30] = {"大物", "高数", "c语言"}; 25 /* 命令开关 */ 26 int SWITCH[16] = {0}; 27 /*所有的 函数声明 */ 28 int Menu(); 29 Student* Init(); 30 int CheckNUM(char*); 31 int CheckName(char*); 32 int CheakScore(int score); 33 int Same_NUM(char*); 34 void InputNodeInfo(Student*); 35 void OutputNodeInfo(Student*); 36 Student* SearchFrontNode(Student*); 37 void DeleteNode(Student*); 38 void InsertBefore(); 39 void InputList(); 40 Student* SearchID(char*); 41 Student* SearchName(char*); 42 void SearchDeleteNode(); 43 void OutList(); 44 void SearchPrintNode(); 45 void Compute(); 46 int CmpID(Student*, Student*, int); 47 int CmpSum(Student*, Student*, int); 48 int CmpScore(Student*, Student*, int); 49 Student* SearchMaxNode(int (*cmp)(Student*, Student*, int), int); 50 Student* Sort(int (*cmp)(Student*, Student*, int), int); 51 void OutputToFile(FILE*, Student*, int); 52 void InsertAfter(Student*); 53 void SaveToFile(); 54 void LoadFile(); 55 // void CopyFile(); 56 void InsertToFile(); 57 void FreeList(Student* p); 58 void Stat(); 59 void Quit(); 60 61 /* 主函数 */ 62 int main() 63 { 64 int n; 65 66 while (1) 67 { 68 n = Menu(); // 69 { 70 if (n == 1 || n == 15 || SWITCH[1]) 71 { 72 switch (n) 73 { 74 /* 执行初始化 */ 75 case 1: 76 head = Init(); 77 printf("LOOK...初始化成功\n"); 78 break; 79 /* 创建链表 ,输入学生信息*/ 80 case 2: 81 InputList(); 82 break; 83 /* 查找学号或姓名删除信息 */ 84 case 3: 85 SearchDeleteNode(); 86 break; 87 /* 输出全部学生信息 */ 88 case 4: 89 system("cls"); 90 OutList(); 91 break; 92 /* 按姓名查找学生信息*/ 93 case 5: 94 SearchPrintNode(); 95 break; 96 /* 保存到文件 */ 97 case 6: 98 SaveToFile(); 99 break; 100 /* 从文件中读取学生信息*/ 101 case 7: 102 if (SWITCH[6]) 103 { 104 head = Init(); 105 LoadFile(); 106 } 107 else 108 { 109 printf("当前文件未保存\n"); 110 } 111 break; 112 /* 计算所有学生的总分和平均分 */ 113 case 8: 114 Compute(); 115 SWITCH[8] = 1; 116 printf("计算完毕\n"); 117 break; 118 /* 插入一个学生信息到链表 */ 119 case 9: 120 InsertBefore(); 121 SWITCH[6] = 0; 122 SWITCH[8] = 0; 123 break; 124 // /* 复制文件 */ 125 // case 10: 126 // CopyFile(); 127 break; // 本来想取消复制函数,有一个问题,如果同时取消break 程序会奇怪的出死循环,还没有解决 2013 06 13 128 /* 排序,按总分排序并打印学生信息 */ 129 case 11: 130 if (SWITCH[8]) 131 { 132 head = Sort(CmpSum, 0); 133 system("cls"); 134 OutList(); 135 } 136 else 137 { 138 printf("请先计算总分!\n"); 139 } 140 break; 141 /* 尾部添加一个学生信息到文件中 */ 142 case 12: 143 InsertToFile(); 144 SWITCH[6] = 0; 145 printf("尾部添加完毕!\n"); 146 break; 147 /* 按学号搜索..学生信息*/ 148 case 13: 149 if (SWITCH[8]) 150 { 151 head = Sort(CmpID, 0); 152 system("cls"); 153 OutList(); 154 } 155 else 156 { 157 printf("请先计算总分!\n"); 158 } 159 break; 160 /* 分类汇总 */ 161 case 14: 162 system("cls"); 163 Stat(); 164 break; 165 /* 结束 */ 166 case 15: 167 Quit(); 168 break; 169 default: 170 printf("无效命令编号!\n"); 171 fflush(stdin); 172 } 173 system("pause"); 174 } 175 else 176 { 177 printf("你必须首先初始化!\n"); 178 system("pause"); 179 } 180 } 181 } 182 183 system("pause"); 184 return 0; 185 } 186 187 /* 菜单 */ 188 int Menu() 189 { 190 int n; 191 system("cls"); 192 fflush(stdin); 193 printf("*********************************************************************\n"); 194 printf("*********************************************************************\n"); 195 printf("【01】 初始化........\n"); 196 printf("【02】 输入学生信息\n"); 197 printf("【03】 查找学号或姓名删除信息\n"); 198 printf("【04】 输出全部学生信息\n"); 199 printf("【05】 按姓名查找学生信息\n"); 200 printf("【06】 保存到文件\n"); 201 printf("【07】 从文件中读取学生信息\n"); 202 printf("【08】 计算所有学生的总分和平均分\n"); 203 printf("【09】 插入一个学生信息到链表中\n"); 204 // printf("【10】 复制文件\n"); 205 printf("【11】 按总分排序并打印学生信息\n"); 206 printf("【12】 尾部添加一个学生信息到文件中\n"); 207 printf("【13】 按学号搜索..学生信息\n"); 208 printf("【14】 分类汇总\n"); 209 printf("【15】 退出\n"); 210 printf("********************************************************************\n"); 211 printf("请输入命令编号: "); 212 scanf("%d", &n); 213 return n; 214 } 215 216 /* 初始化 */ 217 Student* Init() 218 { 219 int i; 220 Student *head; 221 head = LEN; 222 head->next = NULL; 223 224 /* 命令开关初始化 */ 225 for (i = 1; i < 16; i++) 226 { 227 SWITCH[i] = 0; 228 } 229 230 SWITCH[1] = 1; 231 SWITCH[6] = 1; 232 return head; 233 } 234 235 /* 检查学号,要求必须是数字 */ 236 int CheckNUM(char* s) 237 { 238 int i; 239 240 if (strlen(s) == 0 || strlen(s) > 10) return 0; 241 for (i = 0; i < strlen(s); i++) 242 { 243 if (s[i] < '0' || s[i] > '9') return 0; 244 } 245 246 return 1; 247 } 248 249 /* 检查姓名,要求必须是英文字母 */ 250 int CheckName(char* s) 251 { 252 int i; 253 254 if (strlen(s) == 0 || strlen(s) > 15) return 0; 255 256 for (i = 0; i < strlen(s); i++) 257 { 258 if (!(s[i] >= 'a' && s[i] <= 'z' || s[i] >= 'A' && s[i] <= 'Z')) return 0; 259 } 260 261 return 1; 262 } 263 264 /* 检查分数 */ 265 int CheakScore(int score) 266 { 267 if (score > 100 || score <= 0) return 0; 268 return 1; 269 } 270 271 /* 检查相同学号 */ 272 int Same_NUM(char* s) 273 { 274 Student *p = head->next; 275 while(p != NULL) 276 { 277 if (strcmp(s, p->num) == 0) return 1; 278 p = p->next; 279 } 280 return 0; 281 } 282 283 /* 给p指向的节点输入信息 */ 284 void InputNodeInfo(Student* p) 285 { int i; 286 fflush(stdin); //实验室人介绍说gcc 下没用 2013 06 07 早 287 288 /* 学号 */ 289 printf("\n请输入学号: "); 290 do 291 { 292 gets(p->num); 293 294 if (!CheckNUM(p->num)) 295 { 296 printf("数据不标准,请重新输入学号: "); 297 } 298 else 299 if (Same_NUM(p->num)) 300 { 301 printf("检测到此学号存在,请重新输入: "); 302 } 303 }while (!(CheckNUM(p->num) && !Same_NUM(p->num))); 304 305 /* 姓名 */ 306 printf("请输入姓名: "); 307 do 308 { 309 gets(p->name); 310 // getchar(); // 2013 06 13增加,会出现死循环现象 311 if (!CheckName(p->name)) 312 { 313 printf("数据不标准,请重新输入姓名: "); 314 } 315 } while (!CheckName(p->name)); 316 317 /* 成绩 */ 318 for (i = 0; i < N; i++) 319 { 320 printf("请输入 %s 成绩: ", CLASSNAME[i]); 321 do 322 { 323 fflush(stdin); 324 scanf("%d", &p->score[i]); 325 326 if (!CheakScore(p->score[i])) 327 { 328 printf("数据不标准,请重新输入 %s 成绩: ", CLASSNAME[i]); 329 } 330 } 331 while (!CheakScore(p->score[i])); 332 getchar(); 333 } 334 335 /* 总分及平均分 */ //后面通过计算得出 336 p->sum = 0; 337 p->ave = 0; 338 } 339 340 /* 输出p指向节点的信息 */ 341 void OutputNodeInfo(Student* p) 342 { 343 int i; 344 printf("\n"); 345 printf("姓名: %s\n", p->name); 346 printf("学号: %s\n", p->num); 347 348 for (i = 0; i < N; i++) 349 { 350 printf("%s 成绩: %d\n", CLASSNAME[i], p->score[i]); 351 } 352 353 /* 计算过才输出 */ 354 if (SWITCH[8]) printf("总分: %d\n", p->sum); 355 if (SWITCH[8]) printf("平均分: %.2lf\n", p->ave); 356 } 357 358 /* 返回r的前一个节点 */ //与删除模块对应,来自范老师的例子 359 Student* SearchFrontNode(Student* r) 360 { 361 Student *p = head; 362 while (p->next != r) 363 p = p->next; 364 return p; 365 } 366 367 /* 删除r指向的节点 */ //删除的思路,保留下自己需要的部分也就是删除不要(哲学思想 空) 368 DeleteNode(Student* r) 369 { 370 Student *p = SearchFrontNode(r); 371 p->next = r->next; 372 } 373 374 /* 头插法插入节点 */ 375 void InsertBefore() 376 { 377 Student *s = LEN; 378 InputNodeInfo(s); 379 s->next = head->next; 380 head->next = s; 381 } 382 383 /* 输入链表 */ 384 void InputList() 385 { 386 int n; 387 printf("有多少个学生信息要输入? "); 388 scanf("%d", &n); 389 getchar(); 390 while (n--) //简化之后 391 { 392 InsertBefore(); 393 } 394 } 395 396 /* 按学号查找 */ 397 Student* SearchID(char* num) 398 { 399 Student *p = head->next; 400 401 while (p != NULL) 402 { 403 if (strcmp(p->num, num) == 0) break; 404 p = p->next; 405 } 406 return p; 407 } 408 409 /* 按姓名查找 */ 410 Student* SearchName(char* name) 411 { 412 Student *p = head->next; 413 414 while (p != NULL) 415 { 416 if (strcmp(p->name, name) == 0) break; 417 p = p->next; 418 } 419 return p; 420 } 421 422 /* 按学号或姓名查找删除节点 */ 423 void SearchDeleteNode() 424 { 425 Student *p; 426 fflush(stdin); 427 char str[20]; 428 char sure[20]; 429 430 /* 输入规范性判断 */ 431 printf("请输入你要删除的学生的 姓名 或 学号: "); 432 do 433 { 434 gets(str); 435 if (!(CheckNUM(str) || CheckName(str))) //多次修改 436 { 437 printf("数据不标准,请重新输入姓名或学号: "); 438 } 439 } while (!(CheckNUM(str) || CheckName(str))); 440 441 /* 判断是姓名还是学号 */ 442 if (str[0] >= '0' && str[0] <= '9') 443 { 444 p = SearchID(str); 445 446 if (p == NULL) 447 { 448 printf("对不起,找不到这个学号\n"); 449 } 450 else 451 { 452 OutputNodeInfo(p); 453 printf("确认删除? (输入\"y\"确认,任意键取消): "); 454 if (strcmp(gets(sure), "y") == 0) 455 { 456 DeleteNode(p); 457 printf("删除成功\n"); 458 SWITCH[6] = 0; //不保存 459 } 460 fflush(stdin); 461 } 462 } 463 else 464 { 465 p = SearchName(str); 466 467 if (p == NULL) 468 { 469 printf("对不起,找不到这个姓名\n"); 470 } 471 else 472 { 473 OutputNodeInfo(p); 474 printf("确认删除? (输入\"y\"确认,任意键取消): "); 475 if (strcmp(gets(sure), "y") == 0) 476 { 477 DeleteNode(p); 478 printf("删除成功!\n"); 479 SWITCH[6] = 0; 480 } 481 fflush(stdin); 482 } 483 } 484 } 485 486 /* 输出链表 */ 487 void OutList() 488 { 489 Student *p = head->next; 490 491 /* 空链表处理 */ 492 if (p == NULL) 493 { 494 printf("暂无学生信息!\n"); 495 } 496 497 while (p != NULL) 498 { 499 OutputNodeInfo(p); 500 p = p->next; 501 } 502 } 503 504 /* 按姓名查找记录并打印 */ 505 void SearchPrintNode() 506 { 507 Student *p = head->next; 508 int ok = 1; 509 char name[20]; 510 fflush(stdin); 511 512 /* 姓名合法性判断 */ 513 printf("请输入你要查找的学生姓名: "); 514 do 515 { getchar(); 516 gets(name); 517 518 if (!CheckName(name)) 519 { 520 printf("数据不标准,请重新输入姓名: "); 521 } 522 } 523 while (!CheckName(name)); 524 525 /* 按姓名查找节点 */ 526 while (p != NULL) 527 { 528 if (strcmp(p->name, name) == 0) 529 { 530 ok = 0; 531 OutputNodeInfo(p); 532 } 533 p = p->next; 534 } 535 536 if (ok) 537 { 538 printf("对不起,找不到这个姓名\n"); 539 } 540 } 541 542 /* 计算总分和均分 */ 543 void Compute() 544 { 545 int i; 546 Student *p = head->next; 547 548 while (p != NULL) 549 { 550 int sum = 0; 551 552 for (i = 0; i < N; i++) 553 { 554 sum += p->score[i]; 555 } 556 557 p->sum = sum; 558 p->ave = sum * 1.0 /N; 559 p = p->next; 560 } 561 } 562 563 /* 比较学号 */ 564 int CmpID(Student* a, Student* b, int k) 565 { 566 return strcmp(a->num, b->num); 567 } 568 569 /* 比较总分 */ 570 int CmpSum(Student* a, Student* b, int k) 571 { 572 return b->sum-a->sum; 573 } 574 575 /* 比较各科分数 */ 576 int CmpScore(Student* a, Student* b, int k) 577 { 578 return b->score[k] - a->score[k]; 579 } 580 581 /* 找出其中的最大元素 */ 582 Student* SearchMaxNode(int (*cmp)(Student* a, Student* b, int k), int k) //借鉴别人,来自网络 583 { 584 Student *p = head->next; 585 Student *max = p; 586 587 while (p != NULL) 588 { 589 if (cmp(p, max, k) < 0) 590 { 591 max = p; 592 } 593 p = p->next; 594 } 595 596 return max; 597 } 598 599 /* 排序 */ 600 Student* Sort(int (*cmp)(Student* a, Student* b, int k), int k) //直接应用的是逗号运算表达试的值为最后一个 P25 601 { 602 Student *newhead = LEN; 603 Student *p = newhead; 604 Student *max; 605 606 while (head->next != NULL) 607 { 608 max = SearchMaxNode(cmp, k); 609 p->next = max; 610 DeleteNode(max); 611 p = p->next; 612 } 613 /* 表尾处理 */ 614 p->next = NULL; 615 return newhead; 616 } 617 /* 将s插入链表尾部 */ 618 void InsertAfter(Student* s) 619 { 620 Student *p = head; 621 622 while (p->next != NULL) 623 p = p->next; 624 s->next = NULL; 625 p->next = s; 626 } 627 628 /* 保存到文件 */ 629 void SaveToFile() 630 { 631 /* 处理尾部添加表尾情况 */ 632 if (SWITCH[12]) 633 { 634 InsertAfter(tmp); 635 } 636 637 FILE *fp; 638 int i; 639 Student *p; 640 char file[20]; 641 fflush(stdin); 642 printf("请输入要保存的文件名: "); 643 scanf("%s",file); 644 getchar(); 645 if ((fp = fopen(file, "wt")) == NULL) 646 { 647 printf("写文件错误.......!\n"); 648 return; 649 } 650 for(p = head->next;p!=NULL;p=p->next) //此段中大括号的使用位置错误直接导致程序出现严重的段错误(linux实验室) 651 { fprintf(fp,"%s %s\n",p->name,p->num ); 652 for(i=0;i<=2;i++) 653 { 654 fprintf(fp,"%d\n",p->score[i]); 655 } 656 } 657 printf("文件保存成功!\n"); 658 fclose(fp); 659 SWITCH[6] = 1; 660 661 /* 处理尾部添加情况 */ 662 if (SWITCH[12]) 663 { 664 DeleteNode(tmp); 665 SWITCH[12] = 0; 666 } 667 } 668 669 /* 从文件中读入记录 */ 670 void LoadFile() 671 { 672 int i; 673 FILE *fp; 674 char file[20]; 675 fflush(stdin); 676 printf("请输入文件名: "); 677 getchar(); 678 gets(file); 679 680 if ((fp = fopen(file, "rt")) == NULL) 681 { 682 printf("对不起,无法打开文件!\n"); 683 return; 684 } 685 686 /* 文件未结束时读入数据 */ 687 while (!feof(fp)) 688 { 689 Student *s = LEN; 690 fscanf(fp, "%s %s", s->name,s->num); 691 for (i = 0; i < N; i++) 692 { 693 fscanf(fp, "%d\n", &s->score[i]); 694 } 695 696 s->next = head->next; 697 head->next = s; 698 } 699 700 printf("文件读取成功!\n"); 701 fclose(fp); 702 } 703 704 /* 复制文件 */ 705 //void CopyFile() 706 //{ 707 // FILE *fp1, *fp2; 708 // char ch, file1[20], file2[20]; 709 // fflush(stdin); 710 // /* 读入源文件 */ 711 // printf("请输入源文件名: "); 712 // gets(file1); 713 // 714 // if ((fp1 = fopen(file1, "rb")) == NULL) 715 // { 716 // printf("对不起,无法打开文件!\n"); 717 // return; 718 // } 719 // 720 // /* 读入目标文件 */ 721 // printf("请输入目标文件名: "); 722 // gets(file2); 723 // 724 // if ((strcmp(file1, file2) == 0) || ((fp2 = fopen(file2, "wb")) == NULL)) 725 // { 726 // printf("对不起,无法创建文件!\n"); 727 // return; 728 // } 729 730 // /* 逐个字符拷贝 */ 731 // while (!feof(fp1)) 732 // { 733 // ch = fgetc(fp1); 734 735 // if (ch != EOF) 736 // fputc(ch, fp2); 737 // } 738 // 739 // fclose(fp1); 740 // fclose(fp2); 741 // printf("文件拷贝成功!\n"); 742 //} 743 744 /* 尾部添加记录到文件中 */ 745 void InsertToFile() 746 { 747 tmp = LEN; 748 InputNodeInfo(tmp); 749 SWITCH[12] = 1; 750 } 751 752 /* 分类统计 */ 753 void Stat() 754 { 755 int i, j, n = 0; 756 int sum[N] = {0}; 757 Student *p = head->next; 758 759 if (p == NULL) 760 { 761 printf("暂无学生信息,无法统计\n"); 762 return; 763 } 764 765 /* 统计各科总分 */ 766 while (p != NULL) 767 { 768 /* 记录学生总数 */ 769 n++; 770 771 for (i = 0; i < N; i++) 772 { 773 sum[i] += p->score[i]; 774 } 775 776 p = p->next; 777 } 778 779 /* 各科分别输出 */ 780 for (i = 0; i < N; i++) 781 { 782 printf("%s 的平均分为: %.2lf\n", CLASSNAME[i], sum[i] * 1.0 / n); 783 head = Sort(CmpScore, i); 784 j = 0; 785 p = head->next; 786 787 while (p != NULL) 788 { 789 j++; 790 printf("第%d名 %s %d\n", j, p->name, p->score[i]); 791 p = p->next; 792 } 793 794 printf("\n"); 795 } 796 } 797 798 /* 释放链表 */ 799 void FreeList(Student* p) 800 { 801 if (p->next != NULL) 802 { 803 FreeList(p->next); 804 } 805 free(p); 806 } 807 808 /* 退出 */ 809 void Quit() 810 { 811 if (!SWITCH[6]) 812 { 813 printf("请先保存文件!\n"); 814 return; 815 } 816 if (head != NULL) 817 { 818 FreeList(head); 819 } 820 exit(0); 821 }
---恢复内容结束---
1 /学生管理系统 完成时间2013 06 08 2 //大一第一次课程设计 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #define N 3 7 #define LEN (Student*) malloc(sizeof(Student)) 8 /* 学生数据结构 */ 9 typedef struct node 10 { 11 char num[20]; 12 char name[15]; 13 int score[N]; 14 int sum; 15 double ave; 16 struct node *next; 17 } Student; 18 19 /* 头指针 */ 20 Student *head = NULL; 21 /* 临时指针 */ 22 Student *tmp = NULL; 23 /* 课程名称 */ 24 char CLASSNAME[N][30] = {"大物", "高数", "c语言"}; 25 /* 命令开关 */ 26 int SWITCH[16] = {0}; 27 /*所有的 函数声明 */ 28 int Menu(); 29 Student* Init(); 30 int CheckNUM(char*); 31 int CheckName(char*); 32 int CheakScore(int score); 33 int Same_NUM(char*); 34 void InputNodeInfo(Student*); 35 void OutputNodeInfo(Student*); 36 Student* SearchFrontNode(Student*); 37 void DeleteNode(Student*); 38 void InsertBefore(); 39 void InputList(); 40 Student* SearchID(char*); 41 Student* SearchName(char*); 42 void SearchDeleteNode(); 43 void OutList(); 44 void SearchPrintNode(); 45 void Compute(); 46 int CmpID(Student*, Student*, int); 47 int CmpSum(Student*, Student*, int); 48 int CmpScore(Student*, Student*, int); 49 Student* SearchMaxNode(int (*cmp)(Student*, Student*, int), int); 50 Student* Sort(int (*cmp)(Student*, Student*, int), int); 51 void OutputToFile(FILE*, Student*, int); 52 void InsertAfter(Student*); 53 void SaveToFile(); 54 void LoadFile(); 55 // void CopyFile(); 56 void InsertToFile(); 57 void FreeList(Student* p); 58 void Stat(); 59 void Quit(); 60 61 /* 主函数 */ 62 int main() 63 { 64 int n; 65 66 while (1) 67 { 68 n = Menu(); // 69 { 70 if (n == 1 || n == 15 || SWITCH[1]) 71 { 72 switch (n) 73 { 74 /* 执行初始化 */ 75 case 1: 76 head = Init(); 77 printf("LOOK...初始化成功\n"); 78 break; 79 /* 创建链表 ,输入学生信息*/ 80 case 2: 81 InputList(); 82 break; 83 /* 查找学号或姓名删除信息 */ 84 case 3: 85 SearchDeleteNode(); 86 break; 87 /* 输出全部学生信息 */ 88 case 4: 89 system("cls"); 90 OutList(); 91 break; 92 /* 按姓名查找学生信息*/ 93 case 5: 94 SearchPrintNode(); 95 break; 96 /* 保存到文件 */ 97 case 6: 98 SaveToFile(); 99 break; 100 /* 从文件中读取学生信息*/ 101 case 7: 102 if (SWITCH[6]) 103 { 104 head = Init(); 105 LoadFile(); 106 } 107 else 108 { 109 printf("当前文件未保存\n"); 110 } 111 break; 112 /* 计算所有学生的总分和平均分 */ 113 case 8: 114 Compute(); 115 SWITCH[8] = 1; 116 printf("计算完毕\n"); 117 break; 118 /* 插入一个学生信息到链表 */ 119 case 9: 120 InsertBefore(); 121 SWITCH[6] = 0; 122 SWITCH[8] = 0; 123 break; 124 // /* 复制文件 */ 125 // case 10: 126 // CopyFile(); 127 break; // 本来想取消复制函数,有一个问题,如果同时取消break 程序会奇怪的出死循环,还没有解决 2013 06 13 128 /* 排序,按总分排序并打印学生信息 */ 129 case 11: 130 if (SWITCH[8]) 131 { 132 head = Sort(CmpSum, 0); 133 system("cls"); 134 OutList(); 135 } 136 else 137 { 138 printf("请先计算总分!\n"); 139 } 140 break; 141 /* 尾部添加一个学生信息到文件中 */ 142 case 12: 143 InsertToFile(); 144 SWITCH[6] = 0; 145 printf("尾部添加完毕!\n"); 146 break; 147 /* 按学号搜索..学生信息*/ 148 case 13: 149 if (SWITCH[8]) 150 { 151 head = Sort(CmpID, 0); 152 system("cls"); 153 OutList(); 154 } 155 else 156 { 157 printf("请先计算总分!\n"); 158 } 159 break; 160 /* 分类汇总 */ 161 case 14: 162 system("cls"); 163 Stat(); 164 break; 165 /* 结束 */ 166 case 15: 167 Quit(); 168 break; 169 default: 170 printf("无效命令编号!\n"); 171 fflush(stdin); 172 } 173 system("pause"); 174 } 175 else 176 { 177 printf("你必须首先初始化!\n"); 178 system("pause"); 179 } 180 } 181 } 182 183 system("pause"); 184 return 0; 185 } 186 187 /* 菜单 */ 188 int Menu() 189 { 190 int n; 191 system("cls"); 192 fflush(stdin); 193 printf("*********************************************************************\n"); 194 printf("*********************************************************************\n"); 195 printf("【01】 初始化........\n"); 196 printf("【02】 输入学生信息\n"); 197 printf("【03】 查找学号或姓名删除信息\n"); 198 printf("【04】 输出全部学生信息\n"); 199 printf("【05】 按姓名查找学生信息\n"); 200 printf("【06】 保存到文件\n"); 201 printf("【07】 从文件中读取学生信息\n"); 202 printf("【08】 计算所有学生的总分和平均分\n"); 203 printf("【09】 插入一个学生信息到链表中\n"); 204 // printf("【10】 复制文件\n"); 205 printf("【11】 按总分排序并打印学生信息\n"); 206 printf("【12】 尾部添加一个学生信息到文件中\n"); 207 printf("【13】 按学号搜索..学生信息\n"); 208 printf("【14】 分类汇总\n"); 209 printf("【15】 退出\n"); 210 printf("********************************************************************\n"); 211 printf("请输入命令编号: "); 212 scanf("%d", &n); 213 return n; 214 } 215 216 /* 初始化 */ 217 Student* Init() 218 { 219 int i; 220 Student *head; 221 head = LEN; 222 head->next = NULL; 223 224 /* 命令开关初始化 */ 225 for (i = 1; i < 16; i++) 226 { 227 SWITCH[i] = 0; 228 } 229 230 SWITCH[1] = 1; 231 SWITCH[6] = 1; 232 return head; 233 } 234 235 /* 检查学号,要求必须是数字 */ 236 int CheckNUM(char* s) 237 { 238 int i; 239 240 if (strlen(s) == 0 || strlen(s) > 10) return 0; 241 for (i = 0; i < strlen(s); i++) 242 { 243 if (s[i] < '0' || s[i] > '9') return 0; 244 } 245 246 return 1; 247 } 248 249 /* 检查姓名,要求必须是英文字母 */ 250 int CheckName(char* s) 251 { 252 int i; 253 254 if (strlen(s) == 0 || strlen(s) > 15) return 0; 255 256 for (i = 0; i < strlen(s); i++) 257 { 258 if (!(s[i] >= 'a' && s[i] <= 'z' || s[i] >= 'A' && s[i] <= 'Z')) return 0; 259 } 260 261 return 1; 262 } 263 264 /* 检查分数 */ 265 int CheakScore(int score) 266 { 267 if (score > 100 || score <= 0) return 0; 268 return 1; 269 } 270 271 /* 检查相同学号 */ 272 int Same_NUM(char* s) 273 { 274 Student *p = head->next; 275 while(p != NULL) 276 { 277 if (strcmp(s, p->num) == 0) return 1; 278 p = p->next; 279 } 280 return 0; 281 } 282 283 /* 给p指向的节点输入信息 */ 284 void InputNodeInfo(Student* p) 285 { int i; 286 fflush(stdin); //实验室人介绍说gcc 下没用 2013 06 07 早 287 288 /* 学号 */ 289 printf("\n请输入学号: "); 290 do 291 { 292 gets(p->num); 293 294 if (!CheckNUM(p->num)) 295 { 296 printf("数据不标准,请重新输入学号: "); 297 } 298 else 299 if (Same_NUM(p->num)) 300 { 301 printf("检测到此学号存在,请重新输入: "); 302 } 303 }while (!(CheckNUM(p->num) && !Same_NUM(p->num))); 304 305 /* 姓名 */ 306 printf("请输入姓名: "); 307 do 308 { 309 gets(p->name); 310 // getchar(); // 2013 06 13增加,会出现死循环现象 311 if (!CheckName(p->name)) 312 { 313 printf("数据不标准,请重新输入姓名: "); 314 } 315 } while (!CheckName(p->name)); 316 317 /* 成绩 */ 318 for (i = 0; i < N; i++) 319 { 320 printf("请输入 %s 成绩: ", CLASSNAME[i]); 321 do 322 { 323 fflush(stdin); 324 scanf("%d", &p->score[i]); 325 326 if (!CheakScore(p->score[i])) 327 { 328 printf("数据不标准,请重新输入 %s 成绩: ", CLASSNAME[i]); 329 } 330 } 331 while (!CheakScore(p->score[i])); 332 getchar(); 333 } 334 335 /* 总分及平均分 */ //后面通过计算得出 336 p->sum = 0; 337 p->ave = 0; 338 } 339 340 /* 输出p指向节点的信息 */ 341 void OutputNodeInfo(Student* p) 342 { 343 int i; 344 printf("\n"); 345 printf("姓名: %s\n", p->name); 346 printf("学号: %s\n", p->num); 347 348 for (i = 0; i < N; i++) 349 { 350 printf("%s 成绩: %d\n", CLASSNAME[i], p->score[i]); 351 } 352 353 /* 计算过才输出 */ 354 if (SWITCH[8]) printf("总分: %d\n", p->sum); 355 if (SWITCH[8]) printf("平均分: %.2lf\n", p->ave); 356 } 357 358 /* 返回r的前一个节点 */ //与删除模块对应,来自范老师的例子 359 Student* SearchFrontNode(Student* r) 360 { 361 Student *p = head; 362 while (p->next != r) 363 p = p->next; 364 return p; 365 } 366 367 /* 删除r指向的节点 */ //删除的思路,保留下自己需要的部分也就是删除不要(哲学思想 空) 368 DeleteNode(Student* r) 369 { 370 Student *p = SearchFrontNode(r); 371 p->next = r->next; 372 } 373 374 /* 头插法插入节点 */ 375 void InsertBefore() 376 { 377 Student *s = LEN; 378 InputNodeInfo(s); 379 s->next = head->next; 380 head->next = s; 381 } 382 383 /* 输入链表 */ 384 void InputList() 385 { 386 int n; 387 printf("有多少个学生信息要输入? "); 388 scanf("%d", &n); 389 getchar(); 390 while (n--) //简化之后 391 { 392 InsertBefore(); 393 } 394 } 395 396 /* 按学号查找 */ 397 Student* SearchID(char* num) 398 { 399 Student *p = head->next; 400 401 while (p != NULL) 402 { 403 if (strcmp(p->num, num) == 0) break; 404 p = p->next; 405 } 406 return p; 407 } 408 409 /* 按姓名查找 */ 410 Student* SearchName(char* name) 411 { 412 Student *p = head->next; 413 414 while (p != NULL) 415 { 416 if (strcmp(p->name, name) == 0) break; 417 p = p->next; 418 } 419 return p; 420 } 421 422 /* 按学号或姓名查找删除节点 */ 423 void SearchDeleteNode() 424 { 425 Student *p; 426 fflush(stdin); 427 char str[20]; 428 char sure[20]; 429 430 /* 输入规范性判断 */ 431 printf("请输入你要删除的学生的 姓名 或 学号: "); 432 do 433 { 434 gets(str); 435 if (!(CheckNUM(str) || CheckName(str))) //多次修改 436 { 437 printf("数据不标准,请重新输入姓名或学号: "); 438 } 439 } while (!(CheckNUM(str) || CheckName(str))); 440 441 /* 判断是姓名还是学号 */ 442 if (str[0] >= '0' && str[0] <= '9') 443 { 444 p = SearchID(str); 445 446 if (p == NULL) 447 { 448 printf("对不起,找不到这个学号\n"); 449 } 450 else 451 { 452 OutputNodeInfo(p); 453 printf("确认删除? (输入\"y\"确认,任意键取消): "); 454 if (strcmp(gets(sure), "y") == 0) 455 { 456 DeleteNode(p); 457 printf("删除成功\n"); 458 SWITCH[6] = 0; //不保存 459 } 460 fflush(stdin); 461 } 462 } 463 else 464 { 465 p = SearchName(str); 466 467 if (p == NULL) 468 { 469 printf("对不起,找不到这个姓名\n"); 470 } 471 else 472 { 473 OutputNodeInfo(p); 474 printf("确认删除? (输入\"y\"确认,任意键取消): "); 475 if (strcmp(gets(sure), "y") == 0) 476 { 477 DeleteNode(p); 478 printf("删除成功!\n"); 479 SWITCH[6] = 0; 480 } 481 fflush(stdin); 482 } 483 } 484 } 485 486 /* 输出链表 */ 487 void OutList() 488 { 489 Student *p = head->next; 490 491 /* 空链表处理 */ 492 if (p == NULL) 493 { 494 printf("暂无学生信息!\n"); 495 } 496 497 while (p != NULL) 498 { 499 OutputNodeInfo(p); 500 p = p->next; 501 } 502 } 503 504 /* 按姓名查找记录并打印 */ 505 void SearchPrintNode() 506 { 507 Student *p = head->next; 508 int ok = 1; 509 char name[20]; 510 fflush(stdin); 511 512 /* 姓名合法性判断 */ 513 printf("请输入你要查找的学生姓名: "); 514 do 515 { getchar(); 516 gets(name); 517 518 if (!CheckName(name)) 519 { 520 printf("数据不标准,请重新输入姓名: "); 521 } 522 } 523 while (!CheckName(name)); 524 525 /* 按姓名查找节点 */ 526 while (p != NULL) 527 { 528 if (strcmp(p->name, name) == 0) 529 { 530 ok = 0; 531 OutputNodeInfo(p); 532 } 533 p = p->next; 534 } 535 536 if (ok) 537 { 538 printf("对不起,找不到这个姓名\n"); 539 } 540 } 541 542 /* 计算总分和均分 */ 543 void Compute() 544 { 545 int i; 546 Student *p = head->next; 547 548 while (p != NULL) 549 { 550 int sum = 0; 551 552 for (i = 0; i < N; i++) 553 { 554 sum += p->score[i]; 555 } 556 557 p->sum = sum; 558 p->ave = sum * 1.0 /N; 559 p = p->next; 560 } 561 } 562 563 /* 比较学号 */ 564 int CmpID(Student* a, Student* b, int k) 565 { 566 return strcmp(a->num, b->num); 567 } 568 569 /* 比较总分 */ 570 int CmpSum(Student* a, Student* b, int k) 571 { 572 return b->sum-a->sum; 573 } 574 575 /* 比较各科分数 */ 576 int CmpScore(Student* a, Student* b, int k) 577 { 578 return b->score[k] - a->score[k]; 579 } 580 581 /* 找出其中的最大元素 */ 582 Student* SearchMaxNode(int (*cmp)(Student* a, Student* b, int k), int k) //借鉴别人,来自网络 583 { 584 Student *p = head->next; 585 Student *max = p; 586 587 while (p != NULL) 588 { 589 if (cmp(p, max, k) < 0) 590 { 591 max = p; 592 } 593 p = p->next; 594 } 595 596 return max; 597 } 598 599 /* 排序 */ 600 Student* Sort(int (*cmp)(Student* a, Student* b, int k), int k) //直接应用的是逗号运算表达试的值为最后一个 P25 601 { 602 Student *newhead = LEN; 603 Student *p = newhead; 604 Student *max; 605 606 while (head->next != NULL) 607 { 608 max = SearchMaxNode(cmp, k); 609 p->next = max; 610 DeleteNode(max); 611 p = p->next; 612 } 613 /* 表尾处理 */ 614 p->next = NULL; 615 return newhead; 616 } 617 /* 将s插入链表尾部 */ 618 void InsertAfter(Student* s) 619 { 620 Student *p = head; 621 622 while (p->next != NULL) 623 p = p->next; 624 s->next = NULL; 625 p->next = s; 626 } 627 628 /* 保存到文件 */ 629 void SaveToFile() 630 { 631 /* 处理尾部添加表尾情况 */ 632 if (SWITCH[12]) 633 { 634 InsertAfter(tmp); 635 } 636 637 FILE *fp; 638 int i; 639 Student *p; 640 char file[20]; 641 fflush(stdin); 642 printf("请输入要保存的文件名: "); 643 scanf("%s",file); 644 getchar(); 645 if ((fp = fopen(file, "wt")) == NULL) 646 { 647 printf("写文件错误.......!\n"); 648 return; 649 } 650 for(p = head->next;p!=NULL;p=p->next) //此段中大括号的使用位置错误直接导致程序出现严重的段错误(linux实验室) 651 { fprintf(fp,"%s %s\n",p->name,p->num ); 652 for(i=0;i<=2;i++) 653 { 654 fprintf(fp,"%d\n",p->score[i]); 655 } 656 } 657 printf("文件保存成功!\n"); 658 fclose(fp); 659 SWITCH[6] = 1; 660 661 /* 处理尾部添加情况 */ 662 if (SWITCH[12]) 663 { 664 DeleteNode(tmp); 665 SWITCH[12] = 0; 666 } 667 } 668 669 /* 从文件中读入记录 */ 670 void LoadFile() 671 { 672 int i; 673 FILE *fp; 674 char file[20]; 675 fflush(stdin); 676 printf("请输入文件名: "); 677 getchar(); 678 gets(file); 679 680 if ((fp = fopen(file, "rt")) == NULL) 681 { 682 printf("对不起,无法打开文件!\n"); 683 return; 684 } 685 686 /* 文件未结束时读入数据 */ 687 while (!feof(fp)) 688 { 689 Student *s = LEN; 690 fscanf(fp, "%s %s", s->name,s->num); 691 for (i = 0; i < N; i++) 692 { 693 fscanf(fp, "%d\n", &s->score[i]); 694 } 695 696 s->next = head->next; 697 head->next = s; 698 } 699 700 printf("文件读取成功!\n"); 701 fclose(fp); 702 } 703 704 /* 复制文件 */ 705 //void CopyFile() 706 //{ 707 // FILE *fp1, *fp2; 708 // char ch, file1[20], file2[20]; 709 // fflush(stdin); 710 // /* 读入源文件 */ 711 // printf("请输入源文件名: "); 712 // gets(file1); 713 // 714 // if ((fp1 = fopen(file1, "rb")) == NULL) 715 // { 716 // printf("对不起,无法打开文件!\n"); 717 // return; 718 // } 719 // 720 // /* 读入目标文件 */ 721 // printf("请输入目标文件名: "); 722 // gets(file2); 723 // 724 // if ((strcmp(file1, file2) == 0) || ((fp2 = fopen(file2, "wb")) == NULL)) 725 // { 726 // printf("对不起,无法创建文件!\n"); 727 // return; 728 // } 729 730 // /* 逐个字符拷贝 */ 731 // while (!feof(fp1)) 732 // { 733 // ch = fgetc(fp1); 734 735 // if (ch != EOF) 736 // fputc(ch, fp2); 737 // } 738 // 739 // fclose(fp1); 740 // fclose(fp2); 741 // printf("文件拷贝成功!\n"); 742 //} 743 744 /* 尾部添加记录到文件中 */ 745 void InsertToFile() 746 { 747 tmp = LEN; 748 InputNodeInfo(tmp); 749 SWITCH[12] = 1; 750 } 751 752 /* 分类统计 */ 753 void Stat() 754 { 755 int i, j, n = 0; 756 int sum[N] = {0}; 757 Student *p = head->next; 758 759 if (p == NULL) 760 { 761 printf("暂无学生信息,无法统计\n"); 762 return; 763 } 764 765 /* 统计各科总分 */ 766 while (p != NULL) 767 { 768 /* 记录学生总数 */ 769 n++; 770 771 for (i = 0; i < N; i++) 772 { 773 sum[i] += p->score[i]; 774 } 775 776 p = p->next; 777 } 778 779 /* 各科分别输出 */ 780 for (i = 0; i < N; i++) 781 { 782 printf("%s 的平均分为: %.2lf\n", CLASSNAME[i], sum[i] * 1.0 / n); 783 head = Sort(CmpScore, i); 784 j = 0; 785 p = head->next; 786 787 while (p != NULL) 788 { 789 j++; 790 printf("第%d名 %s %d\n", j, p->name, p->score[i]); 791 p = p->next; 792 } 793 794 printf("\n"); 795 } 796 } 797 798 /* 释放链表 */ 799 void FreeList(Student* p) 800 { 801 if (p->next != NULL) 802 { 803 FreeList(p->next); 804 } 805 free(p); 806 } 807 808 /* 退出 */ 809 void Quit() 810 { 811 if (!SWITCH[6]) 812 { 813 printf("请先保存文件!\n"); 814 return; 815 } 816 if (head != NULL) 817 { 818 FreeList(head); 819 } 820 exit(0); 821 }