现在的位置: 首页 > 综合 > 正文

重写了一个学生管理程序(作业题)更新版

2013年10月10日 ⁄ 综合 ⁄ 共 12159字 ⁄ 字号 评论关闭

前几天看到CFAN论坛某位同学的作业帖子,决定帮一下,发帖子也是原先的版主,不理人家多不好。

拿到题目一看,是C++的,那位同学给了个源码,是论坛上另外一个同学写的,结构比较混乱,功能也没完善。

他原本的意思是让我修改下,结果我看那个结构,只能重构了。。这个很惭愧的说,不会C++,但是又答应帮人家了,于是拿出勇气来,床头放本Cpp primer,google准备着,vim开开。今天一整天的时间终于搞定了。

第一次写用了对象的C++程序,很多地方没有设置检查,溢出漏洞多多,虽然使用了类,但看起来很是面向过程的。毕竟第一次留个纪念。

更新信息:感谢徐老师的意见,于是决定把搜索那块重新写下,新建了一个搜索模板函数searchframe(),想查找什么内容,怎么比较,查询后是否修改可以由参数指定,增强了代码的复用性。而且可以为以后添加更多的查询/修改功能提供了条件。不过写的水平不怎么高,代码有点晦涩 。。

————————————————————————————————————————————————————————

题目要求:

设计一个类CStudent,类中包含一个学生的基本数据如下:

编号,姓名,性别,年龄,数学成绩,计算机成绩,外语成绩。 并假设编号为整数,且从1号往后连续编码;姓名为字符串,性别为字符。

如: 1 LiPing m 18 89 98 94

请采用binary文件形式,并使用随机读写处理方式,对自定义CStudent类的对象数据进行存储与读写处理(即是说,总按具有连续编码的编号num为“序”来对文件中的各对象数据进行随机读写处理)。并设计该类的成员函数,而且对输出运算符“<<”进行重载,使该运算符能够完成将一个学生的信息输出到屏幕上。

要求成员函数完成以下功能:

(1) 从键盘输入一个学生的有关信息,并将它们存入到数据文件中(按编号来确定写出位置)。

(2) 按编号对学生信息进行检索并将检索结果显示在屏幕上。

(3) 按姓名对学生信息进行检索并将检索结果显示在屏幕上。

(4) 计算某编号学生的总成绩与平均成绩。

(5) 列出所有总成绩超过n分的性别为s同学的有关信息(n,s由用户从键盘输入)。

 

Code:
  1. /**************************************** 
  2. *名称:    student.cpp         * 
  3. *描述:    学生管理程序          * 
  4. *功能:    添加,修改,按条件查询学生信息 * 
  5. *环境:    Fedora Linux 11 & GCC & x86 * 
  6. *备注:    davelv第一次Class于2010-01-10   * 
  7. *更新:    新建了可复用的搜索模板searchframe  * 
  8. ****************************************/  
  9.   
  10. #include <iostream>  
  11. #include <cstring>  
  12. #include <vector>  
  13. #include <fstream>  
  14. #include <cstdlib>  
  15.   
  16. using namespace std;  
  17. #define CIN_LEN     1024//缓冲区长度  
  18. #define FILENAME    "data"//数据文件名  
  19. /////////////////////////////////////  
  20. //            结构和类            //  
  21. ///////////////////////////////////  
  22. struct data//学生个人信息  
  23. {  
  24.     int id;//学号  
  25.     char name[20];//名字  
  26.     char major[20];//专业  
  27.     char sex;//性别  
  28.     double ch,en,ma;//成绩  
  29.     int grade;//年级  
  30. };  
  31.   
  32. class CStudent  
  33. {  
  34. protected:  
  35.     bool altered;//是否修改  
  36.     data info;//学生信息  
  37. public:  
  38.     static int nowid ;//新学生自增id  
  39.     static void displayhead();//显示表头  
  40.     static void displayshorthead();//显示短表头  
  41.     CStudent();//构造  
  42.     void displayinfo();//显示全部学生信息  
  43.     void displayshortinfo();//显示学生短信息  
  44.     double getsum();//取总成绩  
  45.     double getave();//取得平均分  
  46.     double getch();//取语文成绩  
  47.     double geten();//取外语成绩  
  48.     double getma();//取数学成绩  
  49.     int set(bool isnew);//设置学生信息  
  50.     int getgrade();//取年级  
  51.     int getid();//取学号  
  52.     bool isaltered();//取是否修改  
  53.     char getsex();//取性别  
  54.     char* getname();//取姓名  
  55.     char* getmajor();//取专业  
  56.     data* getinfo();//取学生全部信息  
  57.     //定义友元函数以便重载运算符  
  58.     friend ostream& operator<<(ostream&,const CStudent&);  
  59.     friend istream& operator>>(istream&,CStudent&);  
  60.   
  61. };  
  62.   
  63. int CStudent::nowid = 1;//初始化类静态成员  
  64.   
  65. CStudent::CStudent()//基类构造  
  66. {  
  67.     info.id=CStudent::nowid++;//子增id  
  68.     strcpy(info.name,"None");//名字  
  69.     info.ch=0;//语文成绩  
  70.     info.en=0;//外语成绩  
  71.     info.ma=0;//数学成绩  
  72.     info.grade=1;//年级  
  73.     altered=false;//未被修改  
  74. }  
  75.   
  76. int CStudent::getgrade()  
  77. {  
  78.     return info.grade;  
  79. }  
  80.   
  81. double CStudent::getsum()  
  82. {  
  83.     return info.ch+info.en+info.ma;  
  84. }  
  85. double CStudent::getave()  
  86. {  
  87.     return (info.ch+info.en+info.ma)/3;  
  88. }  
  89. double CStudent::getch()  
  90. {  
  91.      return info.ch;  
  92. }  
  93.   
  94. double CStudent::geten()  
  95. {  
  96.     return info.en;  
  97. }  
  98.   
  99. double CStudent::getma()  
  100. {  
  101.     return info.ma;  
  102. }  
  103.   
  104. int CStudent::getid()  
  105. {  
  106.     return info.id;  
  107. }  
  108.   
  109. char CStudent::getsex()  
  110. {  
  111.     return info.sex;  
  112. }  
  113.   
  114. char * CStudent::getname()  
  115. {  
  116.     return info.name;  
  117. }  
  118. bool CStudent::isaltered()  
  119. {  
  120.     return altered;  
  121. }  
  122. data *CStudent::getinfo()  
  123. {  
  124.     return &info;  
  125. }  
  126. void CStudent::displayinfo()  
  127. {  
  128.     cout<<*this<<"/t"<<getsum()<<"/t"<<getave()<<endl;//利用重载运算符输出  
  129. }  
  130. void CStudent::displayshortinfo()  
  131. {  
  132.     cout << *this<<endl;  
  133. }  
  134. void CStudent::displayhead()  
  135. {  
  136.     cout<<"/n/t学号/t姓名/t性别/t专业/t年级/t中文/t英文/t数学/t总分/t平均分/n";  
  137. }  
  138. void CStudent::displayshorthead()  
  139. {  
  140.     cout<<"/n/t学号/t姓名/t性别/t专业/t年级/t中文/t英文/t数学/n";  
  141. }  
  142. int CStudent::set(bool isalter)  
  143. {  
  144.     cout<<"输入学生信息:/n";  
  145.     displayshorthead();  
  146.     if (isalter)  
  147.         displayshortinfo();  
  148.     cout<<"/t"<<info.id<<"/t";  
  149.     cin.clear();  
  150.     cin>> *this;//从标准输入获取学生信息  
  151.     altered=true;//已修改  
  152.   
  153.     if(cin.fail())  
  154.     {  
  155.         cout<<"录入失败/n";  
  156.         cin.clear();  
  157.         cin.ignore(CIN_LEN,'/n');//这两行是用来清空输入缓冲  
  158.         return -1;  
  159.     }  
  160.     else  
  161.     {  
  162.         cout<<"录入成功/n";  
  163.         return 1;  
  164.     }  
  165. }  
  166.   
  167. //重载输出符  
  168. ostream &operator<<(ostream& out,const CStudent &right)  
  169. {  
  170.     //输出学生的全部信息  
  171.     out <<"/t"<<right.info.id<<"/t"<<right.info.name<<"/t"<<right.info.sex<<"/t"  
  172.         <<right.info.major<<"/t"<<right.info.grade<<"/t"<<right.info.ch<<"/t"  
  173.         <<right.info.en<<"/t"<<right.info.ma;  
  174.     return out;  
  175. }  
  176. //重载输入符  
  177. istream& operator>>(istream& in,CStudent& right)  
  178. {  
  179.     //输入除ID外的其他信息  
  180.     in  >>right.info.name>>right.info.sex>>right.info.major  
  181.         >>right.info.grade>>right.info.ch>>right.info.en>>right.info.ma;  
  182.     return in;  
  183. }  
  184.   
  185. /////////////////////////////////  
  186. //            初始化函数           //  
  187. ////////////////////////////////  
  188. int initial(vector<CStudent*> &stu)  
  189. {  
  190.     fstream file;//输入文件  
  191.     CStudent *p;  
  192.   
  193.     file.open(FILENAME, fstream::in|fstream::binary);//二进制输入打开  
  194.   
  195.     if (!file)//文件是否打开成功  
  196.         return -1;  
  197.     while( file.peek()!=EOF )//是否到文件末尾  
  198.     {  
  199.         p=new CStudent();//新建一个学生对象  
  200.         file.read((char*) p->getinfo(),sizeof(data));//读入学生对象  
  201.         if(file.fail())//检查读入是否失败  
  202.             return -2;  
  203.         stu.push_back(p);//对象加入vector  
  204.     }  
  205.     if(!stu.empty())//如果从文件读入了对象  
  206.         CStudent::nowid = stu.back()->getid()+1;//则自增id设置为最后一个学生id+1  
  207.     file.close();//关闭  
  208.     return stu.size();//返回对象个数  
  209. }  
  210. ////////////////////////////////  
  211. //           信息增加函数         //  
  212. ///////////////////////////////  
  213. void insert(vector<CStudent*> &stu)  
  214. {  
  215.     char c='y';//输入控制字符  
  216.   
  217.     int flag = 1;//标志位,1表示新增成功  
  218.   
  219.     CStudent *p=new CStudent();  
  220.   
  221.     while(c != 'n')//是否继续新增  
  222.     {  
  223.         flag = p->set(false);//设置学生信息  
  224.         if( flag == 1 )//如果设置成功  
  225.         {  
  226.             stu.push_back(p);//对象加入vector  
  227.             p = new CStudent();//新建下一个对象  
  228.         }  
  229.         cout << "是否继续添加学生(any/n)?";  
  230.         cin.clear();  
  231.         cin.ignore(CIN_LEN,'/n');  
  232.         cin.get(c);  
  233.     }  
  234.     //删除最后一个新建的对象,因为没有使用它  
  235.     delete p;  
  236.     CStudent::nowid--;  
  237. }  
  238.   
  239. ///////////////////////////////  
  240. //       查询全部信息函数        //  
  241. /////////////////////////////  
  242. int comparebynone(const void *a, const void *b )  
  243. {  
  244.     return 0;  
  245. }  
  246. ////////////////////////////////  
  247. //         按学号比较函数         //  
  248. //////////////////////////////  
  249. int comparebyid(const void *a, const void *b )  
  250. {  
  251.     return *(const int *)a - ((CStudent *)(b))->getid();  
  252. }  
  253. ///////////////////////////////  
  254. //         按姓名比较函数        //  
  255. //////////////////////////////  
  256. int comparebyname(const void *a, const void *b )  
  257. {  
  258.     return strcmp((const char *)a, (const char *)(((CStudent *)b)->getname()));  
  259. }  
  260. ////////////////////////////////  
  261. //         按年级比较函数         //  
  262. //////////////////////////////  
  263. int comparebygrade(const void *a, const void *b)  
  264. {  
  265.     return (*(const int *)a - ((CStudent *)b)->getgrade());  
  266. }  
  267. /////////////////////////////////////  
  268. //        按总分和性别比较函数          //  
  269. ///////////////////////////////////  
  270. int comparebymarkandsex(const void *a, const void *b)  
  271. {  
  272.     double mark;  
  273.     char sex;  
  274.     sscanf((const char*)a,"%lf%c",&mark,&sex);  
  275.     return  !(  
  276.            ( ((CStudent*)b)->getsum() >= mark )  
  277.         && ( (sex =='n') || (sex == ((CStudent*)b)->getsex()) )  
  278.         );  
  279.   
  280.   
  281. }  
  282. ///////////////////////////////  
  283. //         搜索模板              //  
  284. /////////////////////////////  
  285. template <typename T>  
  286. void searchframe(const char *info, T &condition ,vector<CStudent *> &stu, int (*compare)(const void *a, const void *b) ,bool isalter)  
  287. {  
  288.     char c='y';  
  289.     int flag;  
  290.     while(c != 'n')  
  291.     {  
  292.         cin.clear();  
  293.   
  294.         if(info != NULL)  
  295.         {  
  296.             cout<< "输入"<<info<<":";  
  297.             //cin.ignore(CIN_LEN,'/n');  
  298.             cin>>condition;  
  299.         }  
  300.   
  301.         if(cin.fail())  
  302.         {  
  303.             cout << "输入错误/n";  
  304.         }  
  305.         else  
  306.         {  
  307.             //遍历vector查找  
  308.             for(vector<CStudent*>::size_type ix =flag=0; ix!=stu.size(); ++ix)  
  309.             {   //判断是name是否相等  
  310.                 if(compare(&condition,stu[ix]) == 0)  
  311.                 {  
  312.                     if( isalter )  
  313.                         stu[ix]->set(isalter);  
  314.                     else  
  315.                     {  
  316.                         if(flag == 0)  
  317.                             CStudent::displayhead();  
  318.                         stu[ix]->displayinfo();  
  319.                     }  
  320.                     flag = 1;  
  321.                 }  
  322.             }  
  323.             if (flag == 0)//没有查到  
  324.             {  
  325.                 cout<<"没有";  
  326.                 if(info == NULL)  
  327.                     cout<<"符合条件";  
  328.                 else  
  329.                     cout<<info<<"为"<<condition;  
  330.                 cout<<"的学生/n";  
  331.             }  
  332.         }  
  333.         cout << "是否继续(any/n)?";  
  334.         cin.clear();  
  335.         cin.ignore(CIN_LEN,'/n');  
  336.         cin.get(c);  
  337.     }  
  338. }  
  339.   
  340. ////////////////////////////////  
  341. //         信息检索函数           //  
  342. //////////////////////////////  
  343. void fetch(vector<CStudent*> &stu)  
  344. {  
  345.     int choose,id,grade;  
  346.     char name[20],markandsex[20];  
  347.   
  348.     while (true)  
  349.     {  
  350.         cout << "/n/t1.显示全部学生信息/n"  
  351.             "/t2.按学号查学生信息/n"  
  352.             "/t3.按姓名查学生信息/n"  
  353.             "/t4.按年级查学生信息/n"  
  354.             "/t5.按成绩和性别查询/n"  
  355.             "/t6.返回上级菜单/n/n";  
  356.     lchoose:  
  357.         cout<<"输入您的选择:";  
  358.         choose=0;  
  359.         cin>>choose;  
  360.         switch(choose)  
  361.         {  
  362.             case 1 :searchframe(NULL,choose,stu,comparebynone,false);  break;  
  363.             case 2 :searchframe("学号",id,stu,comparebyid,false);  break;  
  364.             case 3 :searchframe("姓名",name,stu,comparebyname,false); break;  
  365.             case 4 :searchframe("年级",grade,stu,comparebygrade,false); break;  
  366.             case 5 :searchframe("分数和性别",markandsex,stu,comparebymarkandsex,false); break;  
  367.             case 6 :return ;  
  368.             default: cout<<"输入有误/n";cin.clear();cin.ignore(CIN_LEN,'/n');goto lchoose;  
  369.         }  
  370.     }  
  371. }  
  372. ////////////////////////////////  
  373. //         信息保存函数           //  
  374. //////////////////////////////  
  375. int save(vector<CStudent*> &stu)  
  376. {  
  377.     fstream file;  
  378.   
  379.     file.open(FILENAME, fstream::out|fstream::binary);//二进制写打开文件  
  380.     if (!file)//判断打开是否成功  
  381.         return -1;  
  382.     //遍历全部对象  
  383.     for(vector<CStudent*>::size_type ix =0; ix!=stu.size(); ++ix)  
  384.     {   //判断当前对象是否已修改  
  385.         if(stu[ix]->isaltered())  
  386.         {   //修改了则写入文件  
  387.             file.seekp(ix*sizeof(data));  
  388.             file.write((char*) stu[ix]->getinfo(),sizeof(data));  
  389.             //写入是否成功  
  390.             if(file.fail())  
  391.                 return -2;  
  392.         }  
  393.   
  394.     }  
  395.     file.close();  
  396.     return 0;  
  397. }  
  398.   
  399. ///////////////////////////////  
  400. //           主函数             //  
  401. //////////////////////////////  
  402.   
  403. int main()  
  404. {  
  405.     vector<CStudent *> stu ;  
  406.   
  407.     system("clear");//清屏  
  408.     //读入数据文件  
  409.     if(initial(stu)<0)  
  410.     {  
  411.         cout<<"初始化失败,请检查数据文件/""<<FILENAME<<"/"是否完好/n";  
  412.         return -1;  
  413.     }  
  414.   
  415.     int choose;  
  416.     //主菜单循环  
  417.     while(true)  
  418.     {  
  419.         cout << "/n                  *----------学生信息管理系统----------*/n/n"  
  420.             "                              1.录入信息/n"  
  421.             "                              2.修改信息/n"  
  422.             "                              3.检索学生/n"  
  423.             "                              4.保存数据/n"  
  424.             "                              5.保存退出/n"  
  425.             "                              6.不保存退出/n/n"  
  426.             "                  *---------modify by davelv-----------*/n";  
  427.     lchoose:  
  428.         cout<<"输入您的选择:";  
  429.         choose=0;  
  430.         cin>>choose;  
  431.         switch(choose)  
  432.         {  
  433.             case 1 :insert(stu);break;  
  434.             case 2 :searchframe("学号",choose,stu,comparebyid,true);break;  
  435.             case 3 :fetch(stu);break;  
  436.             case 4 :if(save(stu) <0 )  
  437.                 {  
  438.                     cout<<"保存失败,请检查数据文件/""<<FILENAME<<"/"是否完好/n";  
  439.                 };break;  
  440.             case 5 :if(save(stu) <0 )  
  441.                 {  
  442.                     cout<<"保存失败,请检查数据文件/""<<FILENAME<<"/"是否完好/n";  
  443.                 }return 0;  
  444.             case 6 :return 0;  
  445.             default:cout<<"输入有误/n";cin.clear();cin.ignore(CIN_LEN,'/n');goto lchoose;  
  446.         }  
  447.     }  
  448.     return 0;  
  449. }  

 demo

抱歉!评论已关闭.