学生信息管理系统
这是我们老师的一个大作业,要求如下:
综合训练项目一 线性结构综合训练
目的和要求:线性结构是最基础,也是最重要的一种结构,通过此项训练让学生掌握线性结构的知识;要求编程实现学生成绩管理系统,使学生掌握线性结构的存储 及相关算法设计;设有一个学生文件,其结构为:学号、姓名、数学成绩、英语成绩、计算机成绩、总分、平均分、排名。要求用顺序和链式两种方式进行存储,并 在此基础上实现学生成绩的录入、保存、计算总分和平均分、排名、查询、统计等基本功能。
我最初的代码在:http://my.oschina.net/iamhere/blog/340999
而我现在写的带libxml2的代码如下:
test.c//程序入口,目前只是测试libxml2的部分
#include<stdio.h> #include"stuxml.h" #include"studentList.h" intmain(void){ SLstulist=list_create_file("student.txt"); list_print(stulist); man_create_list(stulist,"student.info.xml"); return0; }
student.h//学生结构及其操作定义
/** *@filestudent.h *定义了保存学生信息的结构体\n *操作学生信息的函数: * * * *@author小代码 */ #ifndefSTUDENT_H_ #defineSTUDENT_H_ #include<stdbool.h> /** *@brief学生对象结构体定义 */ structstudent{ /**@brief学号*/ intstu_id; /**@brief姓名*/ charstu_name[10]; /**@brief数学成绩*/ doublestu_score_math; /**@brief英语成绩*/ doublestu_score_english; /**@brief计算机成绩*/ doublestu_score_computer; /**@brief总成绩*/ doublestu_score_sum; /**@brief平均成绩*/ doublestu_score_avg; /**@brief排名*/ intstu_score_grade; /**@brief直接前驱元素指针*/ structstudent*prev; /**@brief直接后继元素指针*/ structstudent*next; }; /**@brief学生结构体*/ typedefstructstudentSTU; /**@brief学生结构体指针*/ typedefstructstudent*Stu; /** *@brief输出学生信息的标题 */ voidprint_title(); /** *@brief创建一个学生信息对象 * *@paramstu_id学号 *@paramstu_name姓名 *@paramstu_score_math数学成绩 *@paramstu_score_english英语成绩 *@paramstu_score_computer计算机成绩 * *@return指向学生对象结构体的指针 *@retvalNULL创建失败 */ Stustu_create(intstu_id,charstu_name[20],doublestu_score_math,doublestu_score_english,doublestu_score_computer); /** *@brief输出一个学生的信息 * *输出格式为每项占10个空格\n *如果参数为空,则不输出任何内容 * *@paramstu要输出信息的学生对象 */ voidstu_print(Stustu); /** *@brief比较两个学生的平均分 * * *@paramstu1 *@paramstu2 * *@return比较结果 *@retval1stu1->stu_score_avg>stu2->stu_score_avg *@retval0stu1->stu_score_avg=stu2->stu_score_avg *@retval-1stu1->stu_score_avg<stu2->stu_score_avg */ intstu_score_compare(Stustu1,Stustu2); /** *@brief交换两个学生对象的所有成员的值 * *交换成功则返回0\n *如果有任何一个参数为NULL,则返回-1 * *@paramstu1 *@paramstu2 * *@retval0交换成功 *@retval-1交换失败 */ intstu_swap(Stustu1,Stustu2); #endif/*STUDENT_H_*/
student.c//学生操作实现
#include"student.h" #include<stdio.h> #include<stdlib.h> #include<string.h> /** *@brief输出学生信息的标题 */ voidprint_title(){ printf("%-10s","学号"); printf("%-10s","姓名"); printf("%-10s","数学"); printf("%-10s","英语"); printf("%-10s","计算机"); printf("%-10s","总分"); printf("%-10s","平均分"); printf("%-10s\n","排名"); } /** *@brief创建一个学生信息对象 * *@paramstu_id学号 *@paramstu_name姓名 *@paramstu_score_math数学成绩 *@paramstu_score_english英语成绩 *@paramstu_score_computer计算机成绩 * *@return指向学生对象结构体的指针 *@retvalNULL创建失败 */ Stustu_create(intstu_id,charstu_name[10],doublestu_score_computer){ Stustu=(Stu)malloc(sizeof(STU)); if(NULL==stu){ printf("stu_create...动态分配内存失败!"); exit(-1); } stu->stu_id=stu_id; strcpy(stu->stu_name,stu_name); stu->stu_score_math=stu_score_math; stu->stu_score_english=stu_score_english; stu->stu_score_computer=stu_score_computer; stu->stu_score_sum=stu->stu_score_math+stu->stu_score_english +stu->stu_score_computer; stu->stu_score_avg=stu->stu_score_sum/3; stu->stu_score_grade=-1; stu->prev=NULL; stu->next=NULL; returnstu; } /** *@brief输出一个学生的信息 * *输出格式为每项占10个空格\n *如果参数为空,则不输出任何内容 * *@paramstu要输出信息的学生对象 */ voidstu_print(Stustu){ if(NULL==stu){ return; } printf("%-10d",stu->stu_id); printf("%-10s",stu->stu_name); printf("%-10.2f",stu->stu_score_math); printf("%-10.2f",stu->stu_score_english); printf("%-10.2f",stu->stu_score_computer); printf("%-10.2f",stu->stu_score_sum); printf("%-10.2f",stu->stu_score_avg); printf("%-10d",stu->stu_score_grade); putchar('\n'); } /** *@brief比较两个学生的平均分 * * *@paramstu1 *@paramstu2 * *@return比较结果 *@retval1stu1->stu_score_avg>stu2->stu_score_avg *@retval0stu1->stu_score_avg=stu2->stu_score_avg *@retval-1stu1->stu_score_avg<stu2->stu_score_avg */ intstu_score_compare(Stustu1,Stustu2){ intresult=0; if(stu1->stu_score_sum>stu2->stu_score_sum) result=1; if(stu1->stu_score_sum<stu2->stu_score_sum) result=-1; returnresult; } /** *@brief交换两个学生对象的所有成员的值 * *交换成功则返回0\n *如果有任何一个参数为NULL,则返回-1 * *@paramstu1 *@paramstu2 * *@retval0交换成功 *@retval-1交换失败 */ intstu_swap(Stustu1,Stustu2){ if(NULL==stu1||NULL==stu2){ return-1; } intid_tmp=stu1->stu_id; stu1->stu_id=stu2->stu_id; stu2->stu_id=id_tmp; charname_tmp[10]; strcpy(name_tmp,stu1->stu_name); strcpy(stu1->stu_name,stu2->stu_name); strcpy(stu2->stu_name,name_tmp); doublescore_tmp=stu1->stu_score_math; stu1->stu_score_math=stu2->stu_score_math; stu2->stu_score_math=score_tmp; score_tmp=stu1->stu_score_english; stu1->stu_score_english=stu2->stu_score_english; stu2->stu_score_english=score_tmp; score_tmp=stu1->stu_score_computer; stu1->stu_score_computer=stu2->stu_score_computer; stu2->stu_score_computer=score_tmp; stu1->stu_score_sum=stu1->stu_score_math+stu1->stu_score_english +stu1->stu_score_computer; stu1->stu_score_avg=stu1->stu_score_sum/3; stu2->stu_score_sum=stu2->stu_score_math+stu2->stu_score_english +stu2->stu_score_computer; stu2->stu_score_avg=stu2->stu_score_sum/3; return0; }
studentList.h//学生列表定义及其操作声明
/** *@file *定义了学生列表结构体 * *@author小代码 */ #ifndefSTUDENTLIST_H_ #defineSTUDENTLIST_H_ #include"student.h" #include<stdio.h> #include<stdbool.h> /** *@brief学生列表结构体定义 * */ struct_stu_list{ /**@brief链表头指针*/ Stuhead; /**@brief链表尾指针*/ Stulast; }; /**@brief学生链表*/ typedefstruct_stu_listsl; /**@brief指向学生链表的指针*/ typedefstruct_stu_list*SL; /** *@brief创建一个初始化的链表 * *@return指向_stu_list的指针 *@retvalNULL创建失败 */ SLlist_init(); /** *@brief从文件创建一个学生列表 *@paramfile_name含有学生信息的文本文件的文件名 *@return返回学生列表 *@retvalNULL创建失败 */ SLlist_create_file(char*file_name); /** *@brief销毁一个学生信息链表 * *@paramstu_list要销毁的链表的指针 */ voidlist_destroy(SLstu_list); /** *@brief求学生信息链表的长度 * *@paramstu_list要求长度的学生信息链表 * *@return学生信息链表的长度 *@retval-1参数为空 * */ intlist_len(SLstu_list); /** *@brief判断一个链表是否为空 * *@paramstu_list要判断是否为空的链表 * *@retvaltrue为空 *@retvalfalse不为空 * */ boollist_is_empty(SLstu_list); /** *@brief在链表后追加一个元素 * *@paramstu_list要追加元素的链表 *@paramstu要追加的元素 *@return返回的元素的指针 *@retvalNULL追加失败 */ Stulist_append(SLstu_list,Stustu); /** *@brief根据学生的学号删除一个学生的信息 *@paramstu_list保存学生信息的链表 *@paramstu_id要删除的学生的学号 *@return返回被删除的学生 *@retvalNULL删除失败 */ Stulist_delete(SLstu_list,intstu_id); /** *@brief输出一个链表的内容 *如果链表为空或参数为NULl,则没有任何输出 * *@paramstu_list要打印的链表 */ voidlist_print(SLstu_list); doublelist_score_sum(SLstu_list); doublelist_score_avg(SLstu_list); /** *@brief根据学生号查的一个学生对象 * *@paramstu_list保存学生信息的链表 *@paramstu_id要查的的学生的学号 *@paramstu传出查询的学生 *@return查找结果 *@retval-1链表为空 *@retval1查询成功 *@retval0没有查到 */ intlist_search_id(SLstu_list,intstu_id,Stustu); /** *@brief排序链表 *使用选择排序法 * *@paramstu_list要排序的学生链表 */ voidlist_sort_avg(SLstu_list); /** *@brief把一个学生信息链表写入到当前目录中的一个TXT文本文件 *默认文件名为:student.txt\n *根据排序的结果,从1开始对学生信息的stu_score_grade字段赋值 *@paramstu_list要写入到文件的学生链表 *@paramfile_name械写入到的文件名 *@return写入到文件中的链表的指针 */ FILE*list_save_txt(SLstu_list,char*file_name); /** *@brief列出平均分高于60的学生的信息 *@paramstu_list学生信息链表 *@return分数高于60分的学生信息链表 *@note返回一个链表的功能还未实现 */ SLlist_pass(SLstu_list); #endif/*STUDENTLIST_H_*/
studentList.c//学生列表操作实现
#include"studentList.h" #include"student.h" #include<stdio.h> #include<stdlib.h> #include<string.h> /** *@brief创建一个初始化的链表 * *@return指向_stu_list的指针 *@retvalNULL创建失败 */ SLlist_init(){ SLstu_list=(SL)malloc(sizeof(sl)); if(NULL==stu_list){ printf("list_init..动态分配内存失败"); exit(-1); } stu_list->head=stu_create(0,"",0.0,0.0); stu_list->last=stu_create(0,0.0); stu_list->head->prev=NULL; stu_list->head->next=stu_list->last; stu_list->last->prev=stu_list->head; stu_list->last->next=NULL; returnstu_list; } /** *@brief从文件创建一个学生列表 *@paramfile_name含有学生信息的文本文件的文件名 *@return返回学生列表 *@retvalNULL创建失败 */ SLlist_create_file(char*file_name){ FILE*stu_file=fopen(file_name,"r"); if(NULL==stu_file){ returnNULL; } SLstu_list=list_init(); intstu_id=0; charstu_name[10]; doublestu_math=0.0; doublestu_english=0.0; doublestu_computer=0.0; while(EOF !=fscanf(stu_file,"%d\t%s\t%lf\t%lf\t%lf",&stu_id,stu_name,&stu_math,&stu_english,&stu_computer)){ Stustu=stu_create(stu_id,stu_math,stu_english,stu_computer); //stu_print(stu); list_append(stu_list,stu); } returnstu_list; } /** *@brief销毁一个学生信息链表 * *@paramstu_list要销毁的链表的指针 */ voidlist_destroy(SLstu_list){ if(NULL==stu_list){ return; } if(list_is_empty(stu_list)){ free(stu_list); } Stutmp=stu_list->head->next; while(tmp!=stu_list->last){ Stuf=tmp; tmp->prev->next=tmp->next; tmp->next->prev=tmp->prev; tmp=f->next; free(f); } free(stu_list); } /** *@brief求学生信息链表的长度 * *@paramstu_list要求长度的学生信息链表 * *@return学生信息链表的长度 *@retval-1参数为空 * */ intlist_len(SLstu_list){ if(NULL==stu_list){ return-1; } intlen=0; if(list_is_empty(stu_list)){ len=0; } Stutmp=stu_list->head->next; while(tmp!=stu_list->last){ len++; tmp=tmp->next; } returnlen; } /** *@brief判断一个链表是否为空 * *@paramstu_list要判断是否为空的链表 * *@retvaltrue为空 *@retvalfalse不为空 */ boollist_is_empty(SLstu_list){ boolflags=false; if(stu_list->head->next==stu_list->last){ flags=true; } returnflags; } /** *@brief在链表后追加一个元素 * *@paramstu_list要追加元素的链表 *@paramstu要追加的元素 *@return返回的元素的指针 *@retvalNULL追加失败 */ Stulist_append(SLstu_list,Stustu){ if(NULL==stu){ returnNULL; } stu_list->last->prev->next=stu; stu->prev=stu_list->last->prev; stu->next=stu_list->last; stu_list->last->prev=stu; returnstu; } /** *@brief根据学生的学号删除一个学生的信息 *@paramstu_list保存学生信息的链表 *@paramstu_id要删除的学生的学号 *@return返回被删除的学生 *@retvalNULL删除失败 */ Stulist_delete(SLstu_list,intstu_id){ if(NULL==stu_list){ returnNULL; } intlen=list_len(stu_list); if(len<0){ returnNULL; } Stustu=NULL; list_search_id(stu_list,stu_id,stu); stu->next->prev=stu->prev; stu->prev->next=stu->next; free(stu); returnNULL; } /** *@brief输出一个链表的内容 *如果链表为空或参数为NULl,则没有任何输出 * *@paramstu_list要打印的链表 */ voidlist_print(SLstu_list){ if(list_is_empty(stu_list)){ return; } print_title(); Stutmp=stu_list->head->next; while(tmp!=stu_list->last){ stu_print(tmp); tmp=tmp->next; } } doublelist_score_sum(SLstu_list){ doublesum=0.0; Stutmp=stu_list->head->next; while(tmp!=stu_list->last){ sum+=tmp->stu_score_math+tmp->stu_score_english +tmp->stu_score_computer; tmp=tmp->next; } returnsum; } doublelist_score_avg(SLstu_list){ returnlist_score_sum(stu_list)/list_len(stu_list); } intlist_search_id(SLstu_list,Stustu){ if(list_is_empty(stu_list)){ return-1; } Stutmp=stu_list->head->next; //inti=1; //intlen=list_len(stu_list); while(tmp!=stu_list->last){ if(tmp->stu_id==stu_id){ break; } tmp=tmp->next; } if(tmp==stu_list->last){ tmp=NULL; return0; } stu->stu_id=tmp->stu_id; strcpy(stu->stu_name,tmp->stu_name); stu->stu_score_math=tmp->stu_score_math; stu->stu_score_english=tmp->stu_score_english; stu->stu_score_computer=tmp->stu_score_computer; return1; } voidlist_sort_avg(SLstu_list){ if(list_is_empty(stu_list)||1==list_len(stu_list)){ return; } Stustu=stu_list->head->next; Stustu_next=stu->next; Stuend=stu_list->last->prev; while(stu!=end){ //stu_print(stu); stu_next=stu->next; while(stu_next!=end->next){ if(stu->stu_score_avg<stu_next->stu_score_avg){ stu_swap(stu,stu_next); } stu_next=stu_next->next; } stu=stu->next; stu_next=stu_next->next; } stu=stu_list->head->next; intgrade=1; while(stu!=stu_list->last){ stu->stu_score_grade=grade; grade++; stu=stu->next; } } FILE*list_save_txt(SLstu_list,char*file_name){ if(list_is_empty(stu_list)){ returnNULL; } FILE*fp=NULL; if(NULL==(fp=fopen(file_name,"w"))){ printf("创建!"); exit(-1); } Stustu=stu_list->head->next; while(stu!=stu_list->last){ charstu_info[1024]; sprintf(stu_info,"%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\n",stu->stu_id,stu->stu_name,stu->stu_score_math,stu->stu_score_english,stu->stu_score_computer,stu->stu_score_sum,stu->stu_score_avg,stu->stu_score_grade); //puts(stu_info); fputs(stu_info,fp); stu=stu->next; } if(0!=fclose(fp)){ puts("关闭文件失败!"); exit(-1); } returnNULL; } SLlist_pass(SLstu_list){ if(list_is_empty(stu_list)){ returnNULL; } Stustu=stu_list->head->next; while(stu!=stu_list->last){ if(stu->stu_score_avg>=60){ stu_print(stu); } stu=stu->next; } returnNULL; }
stuxml.h//xml操作声明
/**@filestuxml.h *@brief学生管理API */ #ifndefSTUMAN_H_ #defineSTUMAN_H_ #include<libxml/tree.h> #include"studentList.h" /**@brief创建一个学生信息的XML文件 * *@paramxml_name该文件的名字,默认为:student.man.xml *@return */ xmlDocPtrman_create_init(char*xml_name); /**@brief根据一个学生列表创建一个保存学生信息的XML文件 * *@paramstulist学生列表 *@paramxml_name文件名称 *@return */ xmlDocPtrman_create_list(SLstulist,char*xml_name); /**@brief根据学生创建一个子结点 * *@paramstu学生 *@return创建的子结点 *@retvalNULL创建失败 */ xmlNodePtrman_create_node(Stustu); #endif/*STUMAN_H_*/
stuxml.c//xml操作实现
#include"stuxml.h" #include"student.h" #include"studentList.h" #include<libxml/tree.h> #include<libxml/parser.h> /**@brief创建一个学生信息的XML文件 * *@paramxml_name该文件的名字,默认为:student.man.xml *@return */ xmlDocPtrman_create_init(char*xml_name){ //文档指针 xmlDocPtrdoc=xmlNewDoc(BAD_CAST"1.0"); xmlNodePtrroot=xmlNewNode(NULL,BAD_CAST"stulist"); //设置XML文档的根属性 xmlDocSetRootElement(doc,root); //保存文档 intnRel=xmlSaveFile(xml_name,doc); if(nRel!=-1){ printf("一个xml文档被创建,写入%d个字节\n",nRel); } returndoc; } /**@brief根据一个学生列表创建一个保存学生信息的XML文件 * *@paramstulist学生列表 *@paramxml_name文件名称 *@return */ xmlDocPtrman_create_list(SLstulist,char*xml_name){ if(NULL==stulist){ puts("NULL==stulist"); returnNULL; } xmlDocPtrdoc=man_create_init(xml_name); xmlNodePtrroot=xmlDocGetRootElement(doc); if(list_is_empty(stulist)){ puts("列表为空"); returndoc; } Stustu=stulist->head->next; while(stu!=stulist->last){ xmlAddChild(root,man_create_node(stu)); stu=stu->next; } //保存文档 intnRel=xmlSaveFile(xml_name,doc); //if(nRel!=-1){ //printf("一个xml文档被创建,写入%d个字节\n",nRel); //} //xmlSaveFileEnc(xml_name,doc,"UTF-8"); nRel=xmlSaveFormatFileEnc(xml_name,"UTF-8",1); printf("一个xml文档被创建,写入%d个字节\n",nRel); xmlFreeDoc(doc); returnNULL; } /**@brief根据学生创建一个子结点 * *@paramstu学生 *@return创建的子结点 *@retvalNULL创建失败 */ xmlNodePtrman_create_node(Stustu){ if(NULL==stu){ returnNULL; } charstr[20]; //创建一个子结点 xmlNodePtrnode=xmlNewNode(NULL,BAD_CAST"student"); //设置id属性 sprintf(str,"%d",stu->stu_id); xmlNewProp(node,BAD_CAST"id",BAD_CASTstr); //设置子结点 xmlNewTextChild(node,NULL,BAD_CAST"stuName",BAD_CASTstu->stu_name); sprintf(str,"%.2lf",stu->stu_score_math); xmlNewTextChild(node,BAD_CAST"stuMath",BAD_CASTstr); sprintf(str,stu->stu_score_english); xmlNewTextChild(node,BAD_CAST"stuEnglish",stu->stu_score_computer); xmlNewTextChild(node,BAD_CAST"stuComputer",stu->stu_score_grade); xmlNewTextChild(node,BAD_CAST"stuGrade",BAD_CASTstr); returnnode; }
输入的文件文件:以Tab键作为分隔符
1001小代码344556 1002老狼251656 1003行者341377 1004天涯341888 1005散人349956
输出的XML文件:
<?xmlversion="1.0"encoding="UTF-8"?> <stulist> <studentid="1001"> <stuName>小代码</stuName> <stuMath>34.00</stuMath> <stuEnglish>45.00</stuEnglish> <stuComputer>56.00</stuComputer> <stuGrade>-1</stuGrade> </student> <studentid="1002"> <stuName>老狼</stuName> <stuMath>25.00</stuMath> <stuEnglish>16.00</stuEnglish> <stuComputer>56.00</stuComputer> <stuGrade>-1</stuGrade> </student> <studentid="1003"> <stuName>行者</stuName> <stuMath>34.00</stuMath> <stuEnglish>13.00</stuEnglish> <stuComputer>77.00</stuComputer> <stuGrade>-1</stuGrade> </student> <studentid="1004"> <stuName>天涯</stuName> <stuMath>34.00</stuMath> <stuEnglish>18.00</stuEnglish> <stuComputer>88.00</stuComputer> <stuGrade>-1</stuGrade> </student> <studentid="1005"> <stuName>散人</stuName> <stuMath>34.00</stuMath> <stuEnglish>99.00</stuEnglish> <stuComputer>56.00</stuComputer> <stuGrade>-1</stuGrade> </student> </stulist>