综合实验 教材管理系统
专业 软件工程 班级: 2017软件工程 学号: 3161206220 姓名: 王博文
实验地点: 工A206/304 实验时间: 2017.12.29 指导教师: 胡锦美
一、实验目的
掌握面向过程的高级语言程序设计的方法与技巧,用C语言在VC++ 6.0编译环境下实现小型应用程序管理系统的开发,让学生对数组、函数、指针、结构体、文件等有更进一步的了解,编制结构清晰、风格良好的C程序。
二、实验内容
某高校的学生教材需要管理,每种教材包含编号、名称、数量、价格、所属专业、作者、出版社和备注信息。编写程序实现如下功能:教材记录的清空、显示、添加、删除、修改、查询等功能。
界面样式不做限制,自由发挥,原则是方便用户操作。
三、实验仪器设备和材料清单
软件配置:Windows XP、Visual C++ 6.0开发环境
硬件配置:CPU P4 2.0G以上、内存 512MB以上
四、实验要求
教材管理程序的各项功能要求编写独立的函数予以实现,并且其所属的各项子功能尽量由独立的函数实现。初始化数据文件时,要求输入密码进行验证。
1、初始化功能:清空所有教材记录。
2、显示功能:从文件中读取教材信息,分别按照教材记录的保存顺序、教材名称的顺序、出版社顺序显示所有教材记录。
3、添加功能:能通过键盘添加新的教材记录并存入文件。
4、删除功能:能根据教材编号删除教材记录。
5、编辑功能:能根据教材编号对教材记录进行编辑修改。
6、查询功能:能根据教材名称、所属专业对教材记录进行查找,并显示其详细信息。
五、实验步骤及结果测试
1.实验方案步骤:
1)应用系统分析,建立系统的功能模块图以及操作界面的组织与设计
2)分析系统各个功能模块的具体内容及模块之间的关系
3)完成各个功能模块函数与主函数的编写
4)完成系统的整合与功能测试
5)完成系统总结报告以及系统使用说明书
2.实验结果测试:
根据系统功能模块的设置,设计相应的测试用例对各个功能进行测试。在老师进行检查时,通过执行用例,向老师展示程序运行的结果。
六、系统使用说明(见 附录-实验结果测试)
七、程序源代码(见 附录-源代码)
八、实验过程分析
问题1:在运行数据载入函数模块的时候,程序老是崩溃。
原因: 添加新结点的方式错误。由于链表中的内存不是一次性连续分配的,因此我们无法保证链表的内存和数组一样是连续的。因此想在链表中找到它的某一个结点,我们只能从头结点开始,沿着指向下一个结点的指针遍历链表直到最后一个结点,并把新的结点接到链表尾。
解决方案:在遍历链表前加上 last=head(last、head都是指针)
问题2:在修复了问题1后,再次运行数据载入函数模块,程序在某些情况下依然会崩溃。
原因: 一开始以为是读取文件的方式错误,后面发现是:每次读取完数据将其存入一个新结点的时候,发生错误。具体原因是在申请新的结点的时候,p->next=NULL;这段代码没有写。所以,新结点所指向的下一个结点不确定,是一个野指针。所以会发生程序崩溃。
解决方案:在申请新结点后,添加p->next=NULL;(p为新申请的结构体指针)
问题3:向一个字符指针赋值时,程序崩溃。
原因: 因为先前char *p=“test”;这样赋值是可以的。但是在程序中运行char *p;scanf(“%s”,p);时发生程序崩溃。
经过查阅和测试得到了答案:因为只定义了char *p,其没有指向内存,要先申请内存(没申请空间就写入当然会崩溃)。
解决方案:将char *p;改写成char p[MAX];因为在定义字符数组时,就已经分配空间了,这也是为什么改成字符数组后程序运行就成功了。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define FILENAME "DATE.TXT" //用来存取数据的文件,前提当前目录必须有这个文件 5 #define PASSWORD "3161206220" //初始化的密码 6 #define MAX 25 //存放字符串最大长度 7 unsigned long count=0; //当前系统记录条数 8 typedef struct System 9 { 10 char SIBN[MAX],name[MAX],pro[MAX],author[MAX],Press[MAX],Note[MAX]; 11 int num; 12 double price; 13 struct System *next; 14 }Book; 15 //与功能无关的显示函数 16 void print(int flag) 17 { 18 if(flag==1) 19 { 20 printf("\n\n"); 21 system("pause"); 22 } 23 else if(flag==2) 24 { 25 printf("当前数据为空,请添加数据!\n\n\n"); 26 system("pause"); 27 } 28 else if(flag==3) 29 { 30 printf("\n\t\t\t\t *欢 迎 来 到 学 生 教 材 管 理 系 统*\n"); 31 printf(" ---------------------------------------------------------------------------------------------------\n\n"); 32 printf("\t\t\t\t\t 注 意 事 项\n"); 33 printf(" 1.在该系统添加或修改数据的时候,需要按正确的格式输入。(如在数量中输入字母是非法的,可能会造成错误)\n"); 34 printf(" 2.所有输入不支持带空格的字符串\n"); 35 printf(" 3.退出系统一定要按照正确的方式(按 G)退出,否则本次所有操作将无法保存\n\n"); 36 printf(" ---------------------------------------------------------------------------------------------------\n\n\n"); 37 system("pause"); 38 system("cls"); 39 } 40 else if(flag==4) 41 { 42 printf("\n\t------------------------------\n"); 43 printf("\t| |\n"); 44 printf("\t| * 感 谢 使 用 * |\n"); 45 printf("\t| |\n"); 46 printf("\t-----------------------------\n\n\n"); 47 } 48 } 49 //数据载入 50 Book* loding(Book *head) 51 { 52 FILE *fp; 53 Book *last; 54 char str[MAX*6]; 55 if((fp=fopen(FILENAME,"r"))==NULL) 56 { 57 printf("打开文件失败!请检查文件名后,重新启动。。。\n"); 58 exit(1); 59 } 60 while(fgets(str,MAX*6,fp)!=NULL) 61 { 62 Book *p; 63 if((p=(Book*)malloc(sizeof(Book)))==NULL) 64 { 65 printf("申请空间失败!\n"); 66 exit(1); 67 } 68 sscanf(str,"%s%s%d%lf%s%s%s%s",p->SIBN,p->name,&p->num, 69 &p->price,p->pro,p->author,p->Press,p->Note); 70 p->next=NULL; 71 if(head) 72 { 73 last=head; 74 while(last->next) last=last->next; 75 last->next=p; 76 } 77 else 78 head=p; 79 count++; 80 } 81 if(fclose(fp)) printf("文件关闭失败!\n"); 82 return head; 83 } 84 //数据保存 85 void out(Book *head) 86 { 87 FILE *fp; 88 Book *last,*p; 89 if((fp=fopen(FILENAME,"w"))==NULL) 90 { 91 printf("打开文件失败!请检查文件名后,重新启动。。。\n"); 92 exit(1); 93 } 94 for(last=head;last;last=last->next) 95 { 96 fprintf(fp,"%s %s %d %lf %s %s %s %s\n",last->SIBN,last->name,last->num, 97 last->price,last->pro,last->author,last->Press,last->Note); 98 } 99 if(fclose(fp)) printf("文件关闭失败!\n"); 100 if(head) 101 { 102 for(last=head;last;last=p) 103 { 104 p=last->next; 105 free(last); 106 } 107 } 108 system("cls"); 109 } 110 //显示菜单 111 void menu() 112 { 113 printf("---------------------------\n"); 114 printf("| 学 生 教 材 管 理 系 统 |\n"); 115 printf("---------------------------\n"); 116 printf("| A.数据初始化 |\n"); 117 printf("| B.显示 |\n"); 118 printf("| C.添加 |\n"); 119 printf("| D.删除 |\n"); 120 printf("| E.编辑 |\n"); 121 printf("| F.查询 |\n"); 122 printf("| G.退出 |\n"); 123 printf("---------------------------\n"); 124 printf("您要执行的操作:___\b\b"); 125 } 126 //初始化功能 127 Book* clear(Book *head) 128 { 129 Book *last,*p; 130 char pass[MAX]; 131 system("cls"); 132 printf("请输入密码:__________\b\b\b\b\b\b\b\b\b\b"); 133 scanf("%s",pass); 134 if(strcmp(pass,PASSWORD)==0) 135 { 136 for(last=head;last;last=p) 137 { 138 p=last->next; 139 free(last); 140 } 141 head=NULL; 142 printf("\n数据初始化成功!\n"); 143 count=0; 144 } 145 else 146 { 147 printf("\n密码错误!\n"); 148 } 149 print(1); 150 return head; 151 } 152 //查询功能 153 void find(Book *head,int flag) 154 { 155 int key=1; 156 unsigned long count_find=0; 157 char str[MAX],temp[MAX]; 158 Book *last; 159 system("cls"); 160 if(flag) 161 printf("请输入要查找的编号:"); 162 else 163 printf("请输入要查找的专业名:"); 164 scanf("%s",str); 165 for(last=head;last;last=last->next) 166 { 167 if(flag) 168 strcpy(temp,last->SIBN); 169 else 170 strcpy(temp,last->pro); 171 if(strcmp(str,temp)==0) 172 { 173 if(key) 174 { 175 printf("\n编号\t\t名称\t\t 数量 价格\t 所属专业\t 作者 出版社\t\t 备注信息\n"); 176 printf("-----------------------------------------------------------------------------------------------------------------\n"); 177 } 178 printf("%-16s%-20s%-7d%-9.2lf",last->SIBN,last->name,last->num,last->price); 179 printf("%-16s%-10s%-21s%-21s\n\n",last->pro,last->author,last->Press,last->Note); 180 count_find++; 181 key=0; 182 if(flag) break; 183 } 184 } 185 if(key) printf("记录中无此专业书!\n"); 186 else 187 { 188 printf("-----------------------------------------------------------------------------------------------------------------\n"); 189 printf("\n当前系统中,共找到 %ld 条符合条件记录\n",count_find); 190 } 191 print(1); 192 return ; 193 } 194 //查找模式选择 195 void find_mode(Book *head) 196 { 197 char choice; 198 system("cls"); 199 if(head==NULL) 200 { 201 print(2); 202 return ; 203 } 204 printf("\n请选择查找方式:\n\nA.编号\nB.所属专业\n\n你的选择是: "); 205 getchar(); 206 scanf("%c",&choice); 207 switch(choice) 208 { 209 case ‘A‘:find(head,1);break; 210 case ‘B‘:find(head,0);break; 211 default:{printf("\n非法输入!\n\n\n");system("pause");} 212 } 213 } 214 //添加功能 215 Book* add(Book *head) 216 { 217 Book *p=NULL,*last; 218 system("cls"); 219 if((p=(Book*)malloc(sizeof(Book)))==NULL) 220 { 221 printf("申请空间失败!\n"); 222 exit(1); 223 } 224 printf("请输入\n"); 225 printf("编号:"); 226 scanf("%s",p->SIBN); 227 for(last=head;last;last=last->next) 228 { 229 if(strcmp(last->SIBN,p->SIBN)==0) 230 { 231 printf("此书已存在记录中!\n\n\n"); 232 free(p); 233 system("pause"); 234 return head; 235 } 236 } 237 printf("名称:"); 238 scanf("%s",p->name); 239 printf("数量:"); 240 scanf("%d",&p->num); 241 printf("价格:"); 242 scanf("%lf",&p->price); 243 printf("所属专业:"); 244 scanf("%s",p->pro); 245 printf("作者:"); 246 scanf("%s",p->author); 247 printf("出版社:"); 248 scanf("%s",p->Press); 249 printf("备注信息:"); 250 getchar(); 251 gets(p->Note); 252 p->next=NULL; 253 if(head) 254 { 255 last=head; 256 while(last->next) last=last->next; 257 last->next=p; 258 } 259 else 260 head=p; 261 count++; 262 printf("\n添加成功!\n"); 263 printf("生成的新记录信息:\n\n"); 264 printf("编号\t\t名称\t\t 数量 价格\t 所属专业\t 作者 出版社\t\t 备注信息\n"); 265 printf("-----------------------------------------------------------------------------------------------------------------\n"); 266 printf("%-16s%-20s%-7d%-9.2lf",p->SIBN,p->name,p->num,p->price); 267 printf("%-16s%-10s%-21s%-21s\n\n",p->pro,p->author,p->Press,p->Note); 268 print(1); 269 return head; 270 } 271 //删除功能 272 Book* del(Book *head) 273 { 274 int flag=0; 275 char SIBN[MAX]; 276 Book *last,*p=NULL; 277 system("cls"); 278 if(head==NULL) 279 { 280 print(2); 281 return head; 282 } 283 printf("请输入要删除的编号:"); 284 scanf("%s",SIBN); 285 if(strcmp(head->SIBN,SIBN)==0) 286 { 287 p=head; 288 head=head->next; 289 free(p); 290 flag=1; 291 } 292 else 293 { 294 for(last=head,p=last->next;p;last=p,p=last->next) 295 { 296 if(strcmp(p->SIBN,SIBN)==0) 297 { 298 last->next=p->next; 299 free(p); 300 flag=1; 301 break; 302 } 303 } 304 } 305 if(flag) {printf("\n删除成功!\n");count--;} 306 else printf("\n当前系统暂无此书\n"); 307 print(1); 308 return head; 309 } 310 //编辑功能 311 void editor(Book *head) 312 { 313 char SIBN[MAX]; 314 Book *last; 315 system("cls"); 316 if(head==NULL) 317 { 318 print(2); 319 return ; 320 } 321 printf("请输入要修改的编号:"); 322 scanf("%s",SIBN); 323 for(last=head;last;last=last->next) 324 if(strcmp(last->SIBN,SIBN)==0) 325 { 326 char choice; 327 printf("\n请选择您要修改的内容:\nA.名称 B.数量 C.价格 D.所属专业\n"); 328 printf("E.作者 F.出版社 G.备注信息 H.全部\n您的选择是:___\b\b"); 329 getchar(); 330 scanf("%c",&choice); 331 switch(choice) 332 { 333 case ‘A‘:{printf("新的名称:");scanf("%s",last->name);}break; 334 case ‘B‘:{printf("新的数量:");scanf("%d",&last->num);}break; 335 case ‘C‘:{printf("新的价格:");scanf("%lf",&last->price);}break; 336 case ‘D‘:{printf("新的所属专业:");scanf("%s",last->pro);}break; 337 case ‘E‘:{printf("新的作者:");scanf("%s",last->author);}break; 338 case ‘F‘:{printf("新的出版社:");scanf("%s",last->Press);}break; 339 case ‘G‘:{printf("新的备注信息:");getchar();gets(last->Note);}break; 340 case ‘H‘:{ 341 printf("新的名称:");scanf("%s",last->name); 342 printf("新的数量:");scanf("%d",&last->num); 343 printf("新的价格:");scanf("%lf",&last->price); 344 printf("新的所属专业:");scanf("%s",last->pro); 345 printf("新的作者:");scanf("%s",last->author); 346 printf("新的出版社:");scanf("%s",last->Press); 347 printf("新的备注信息:");getchar();gets(last->Note); 348 };break; 349 default:{printf("\n非法输入!\n\n\n");print(1);return ;} 350 } 351 printf("\n修改成功!\n\n"); 352 printf("更新后的信息:\n"); 353 printf("编号\t\t名称\t\t 数量 价格\t 所属专业\t 作者 出版社\t\t 备注信息\n"); 354 printf("-----------------------------------------------------------------------------------------------------------------\n"); 355 printf("%-16s%-20s%-7d%-9.2lf",last->SIBN,last->name,last->num,last->price); 356 printf("%-16s%-10s%-21s%-21s\n\n",last->pro,last->author,last->Press,last->Note); 357 break; 358 } 359 if(last==NULL) printf("记录中查无此书!\n"); 360 print(1); 361 return ; 362 363 } 364 //显示功能 365 void show(Book *head,int flag) 366 { 367 unsigned long i,j,k; 368 char str1[MAX],str2[MAX]; 369 Book *p,*last=NULL,temp_Book; 370 system("cls"); 371 if(flag) 372 { 373 if((p=(Book*)malloc(count*sizeof(Book)))==NULL) 374 { 375 printf("申请空间失败!\n"); 376 exit(1); 377 } 378 for(last=head,i=0;last;last=last->next,i++) 379 p[i]=*last; 380 for(i=0;i<count-1;i++) 381 { 382 k=i; 383 for(j=i+1;j<count;j++) 384 { 385 if(flag==1) 386 { 387 strcpy(str1,p[k].name); 388 strcpy(str2,p[j].name); 389 } 390 else 391 { 392 strcpy(str1,p[k].Press); 393 strcpy(str2,p[j].Press); 394 } 395 if(strcmp(str1,str2)>0) 396 k=j; 397 } 398 if(k!=i) 399 { 400 temp_Book=p[i]; 401 p[i]=p[k]; 402 p[k]=temp_Book; 403 } 404 } 405 } 406 printf("\n\t\t\t\t 教 材 数 据 列 表\n"); 407 printf("-----------------------------------------------------------------------------------------------------------------\n"); 408 printf("编号\t\t名称\t\t 数量 价格\t 所属专业\t 作者 出版社\t\t 备注信息\n"); 409 printf("-----------------------------------------------------------------------------------------------------------------\n"); 410 if(flag) 411 { 412 for(i=0;i<count;i++) 413 { 414 printf("%-16s%-20s%-7d%-9.2lf",p[i].SIBN,p[i].name,p[i].num,p[i].price); 415 printf("%-16s%-10s%-21s%-21s\n\n",p[i].pro,p[i].author,p[i].Press,p[i].Note); 416 } 417 free(p); 418 } 419 else 420 for(last=head;last;last=last->next) 421 { 422 printf("%-16s%-20s%-7d%-9.2lf",last->SIBN,last->name,last->num,last->price); 423 printf("%-16s%-10s%-21s%-21s\n\n",last->pro,last->author,last->Press,last->Note); 424 } 425 printf("-----------------------------------------------------------------------------------------------------------------\n"); 426 printf("当前系统中,共有 %ld 条记录\n",count); 427 print(1); 428 } 429 //显示模式选择 430 void show_mode(Book *head) 431 { 432 char choice; 433 system("cls"); 434 if(head==NULL) 435 { 436 print(2); 437 return ; 438 } 439 printf("\n请选择显示方式\n\nA.教材记录的保存顺序\nB.教材名称顺序\nC.出版社顺序\n\n你的选择是: "); 440 getchar(); 441 scanf("%c",&choice); 442 switch(choice) 443 { 444 case ‘A‘:show(head,0);break; 445 case ‘B‘:show(head,1);break; 446 case ‘C‘:show(head,2);break; 447 default:{printf("\n非法输入!\n\n\n");system("pause");} 448 } 449 } 450 int main() 451 { 452 char choice; 453 Book *head=NULL; 454 print(3); 455 head=loding(head); 456 while(1) 457 { 458 menu(); 459 scanf("%c",&choice); 460 switch(choice) 461 { 462 case ‘A‘:head=clear(head);break; 463 case ‘B‘:show_mode(head);break; 464 case ‘C‘:head=add(head);break; 465 case ‘D‘:head=del(head);break; 466 case ‘E‘:editor(head);break; 467 case ‘F‘:find_mode(head);break; 468 case ‘G‘:{out(head);print(4);return 0;} 469 } 470 system("cls"); 471 } 472 return 0; 473 }