C新闻信息管理系统.doc
C+新闻信息管理系统报告2015年 3月 6 日一 课程设计题目与要求包括题目与系统功能要求 已知一个日期类 Date,其数据成员如下 class Date private: int m_year,m_month,m_day; /分别代表一个日期中的年月日 int m_totalDaysYear; /年份 m_year 中的总天数 ; 1. 在此基础上,请完善以下成员函数声明和定义,要求声明为 public 访问标识,且 成员函数在类外定义: 1) 默认的构造函数,要求具有三个默认值分别为 2001(年),1(月)和 1(日) 的形式参数,并在此构造函数内部根据 m_year 的值,计算总天数。 2) 重载赋值操作符。 3) 析构函数。 4) 增加并实现以下类Date的成员函数,其功能和声明如下 int getDaysofYear(); /返回一个日期在当年中的天数,如 2014/ 2/12 返回 43 ;int getRemainingDaysofYear(); /返回一个日期在当年中的余下的天数,如 2014/ 1/12 返回 353; int compare(const Date &date); /比较 date 和当前对象的大小, 分别返回 1,0 和-1 代表当前对象的日期大于, 等于或小于 date ;int operator-(const Date &date); /计算并返回 date 和当前调用对象相差的天数 ;Date operator+(int days); /计算当前对象加上 days 天数的日期,并返回结果 5)定义并实现一个类 Date 的友元函数, 声明和功能如下 friend ostream & operator<<(ostream & out, const Date & date); /按照 年/月/日格式输出, 如 2014/ 1/12 6); 定义一个内联函数,其函数名和形式参数如下: isLeapYear(int year ), 要求返回值为布尔类型,其功能为判断 year 是否是闰 年,闰年返回 true,非闰年返回 false。2. 在上题提基础上,设计一个新闻类,要求能够记录新闻发生的日期、编号(整数 从 1 开始)、新闻类型、新闻标题、发生的地点以及新闻的内容。 该类的部分数据 成员声明如下: class News private: string m_news; /存储新闻内容,假设单词间以空格隔开,无换行符和Tab符, Date m_date; /新闻报道的时间 public: ;实现功能: 1) 实现每条新闻自动编号,编号从 1 开始;2) 某类型新闻在某段时间内发生的次数;如 2013 年 1 月 1 日到 2013 年 12 月 31 日期间体 育类的新闻数目。3) 根据特定关键词搜索相关的新闻,并将其输出到屏幕,如 anti-corruption 4) 统计每条新闻的英文单词数目 5) 可增加和删除新闻, 增加或删除的结果保存到本地文件中 6) 在某日期之后一段时间内报道的新闻,并将其输出到屏幕, 如在 2013/1/14 的 169 天 内报道的新闻 要求: 完善类的设计,实现相应功能,请加以说明你的设计。 数据成员以 m_ 开头,如 m_news, 函数成员请用有意义的英文单词 如上题 getRemainingDaysofYear()。假定新闻类型如下: enum NewsTypeEducation,Politic,Sport,Science,Weather; 每条新闻按以下格式存储在本地文本文件中,ID:123 Date:2014/1/13 Type: Sport Title:AustralianOpen2014:Roger Federer'canget backtohisbest' Address:Australian Content: Stefan Edberg believes he can help get Roger Federer back to his best. The Swedish six-time Grand Slam winner will be a part of Federer's coaching team for 10 weeks in 2014, starting with the Australian Open. Swiss Federer, 32, won the last of his 17 Grand Slams at Wimbledonin2012.二 需求分析,包括问题描述、系统环境、运行要求等1.问题描述 本题中要求书写两个类,一个类为时间类,一个是新闻类。在时间类中,有各种处理时间的函数和重载的函数,如:求一个日期在当年中所占的天数及剩余天数,重载输入和输出运算符,重载加减运算符等。而新闻类则是本题的重点,中间就要实现新闻管理的所有功能。新闻的自动编号、计算相同新闻类型发生的次数、根据关键词搜索新闻、统计新闻字数、增删新闻、输出某日期后面一段时间的新闻等等。2. 系统环境及运行要求 操作系统: Windows 8 开发环境:Microsoft Visual Studio 2013三 概要设计,包括系统流程设计、系统模块设计等 1.系统流程设计2. 系统模块设计时间类:新闻类:管理类:四 详细设计,包括类的函数成员和数据成员设计、界面设计(见问题提示)、及其它模块设计与实现1. 时间类(Date):大纲:数据成员:年、月、日 m_year; m_month; m_day。 函数成员:重载函数、基本函数、功能函数、接口函数。重载函数:加号“+”的重载、减号“-”的重载、输入“>>”的重载、输出“<<”的重载。基本函数:默认构造函数、析构函数。功能函数:计算当前日期在本年中的天数、计算当前日期在本年中还剩余的天数、计算当前日期加上输入天数后日期、比较两日期的大小、判断当前年份是否为瑞年。 实现:1.加减函数的重载 这是一个类对象和内置对象的加减,不同于内置类型的加减,所以需要重载。首先,两个对象的加减不能改变时间Date类对象其本身的值,所以,在Date对象作形参时,参数的传递过程中需要形参必须为const引用类型;对于最后的返回值类型,则根据具体的情况和需要而设定。对于“+”的重载时,我采用数组的方法,首先设定每个月具体的天数,然后在用m_day+days>mm_month-1是否成立来判断,除了第一次成功是days=days-(mmonth-1-m_day)-1外;后面的都是days-=mm_month-1;days=1;这样就可以实现实现对days的减小;具体的内容就不在这儿详述了;而对于“-”,我则是使用了判断的形式,具体不详述。 2.输入输出的重载在题目的要求中,这两个重载函数都是必须声明为友元函数,所以严格意义上来讲这两个函数是不属于Date类的成员的函数;输入输出都有两个形参,一个是功能对象,一个是待处理对象(Date);Date类对象都必须是引用类型,而在输出函数中更必须是const引用,返回值则是另外定义的那个形参。 3.基本函数 默认构造函数:即程序员自己编写一个构造函数,给每个数据成员附上初始值 析构函数:自己给出,便于了解编译器的内在运行。 4.功能函数:getDayssofYear(); /返回一个日期在当年中的天数。这一个函数的设计 本来是十分简单的,先使用一个数据,在其中写入每个月的天数,在二月份加入一 个判断就行,然后用一个for(int i=1;i<m_month;i+)循环将所有的月份的值加 起来;最后加上m_day的值结束;而我却使用了if判断嵌套循环;考虑的情况十分 多不说,好容易出错。getRemainingDaysofYear(); /返回一个日期在当年中的余下 的天数;这一个函数使用365- getDayssofYear()即可;日期的大小比较使用if条件判 断即可; inline bool isleapYear(); /内联函数,判断year是否为闰年;因为这里必 须是内联函数,所以判断必须简单,不能有嵌套的判断语句出现,所以只能使用条 件语句:m_year % 4= 0 && m_year % 100 != 0 | m_year % 400 = 0 ? 1。 2. 新闻类(News): 大纲:数据成员: m_date; m_order; m_type; m_content;m_place;m_title; 函数成员: 接口函数;默认构造函数;重载复制运算函数。 实现:接口函数返回数据成员的应用。 默认构造函数赋给数据成员初始值。 重载“=”函数;使用const引用;返回this指针。3. 管理类(Management): 大纲:数据成员:vector<News> stu; 函数成员:各种功能函数。实现:1.void input();/从文本中读入数据并输出到屏幕;由于我是用的是中文文本;所以输 入较为简单;每遇见一次空格就是一种数据成员输入完毕,接着是下一种类型。注意 刚开始要有一个判断,那便是是否成功打开文件。 2.void show();/将信息显示在屏幕上 ;使用一个for循环就可以完成输出工作。这里 面我们需要考虑的是是输出文本中的内容还是vector容器中的内容;输出文本中的内 容这个函数只能使用一次,而输出vector中的内容则可以多次。所以,我采用了第二 种。 3.void identifier();/对新闻进行编号;使用一个for循环就可以实现对新闻的编号; 编号后将其可入一个新建的文本文件,然后使用show()函数对其结果输出展示。 4. void store();/对新闻进行特定格式的储存;此函数用于使新闻在文本文件中的储存 格式与题目要求的一致。 void lookUp();/计算某段时间内某种类型新闻发生的次数;先输入新闻类型和时间 段;然后使用for循环查找这一类型的新闻,找到后放在一个新的vector容器中;然 后在这个新的容器中找到满足条件的新闻,计数。 5.后面的各种功能函数情况比较复杂,就不具体说明。五 测试,包括对各功能模块的测试1. 菜单显示:2. 自动编号且按规定格输出并储存3. 输出某种新闻在某段时间内发生的次数继续查找:4. 根据特定的关键词搜索新闻5. 统计每条新闻的字数继续统计:6. 增加或删减新闻 (1) 增加新闻:输入后:(2) 删除新闻: 删除前如上图: 删除查找: 删除后:再次删除新输入的新闻:7. 输出某日期后一段日期报道的新闻 第一次查找:第二次查找:8. 计算两个日期相差的时间 瑞年同一年份: 平年同一年份: 不同年份:9. 某个日期加上输入天数后的日期 瑞年: 平年: 计算结果跨年分的:10.比较两日期的大小 同一年份的:同一天的:不同年份的:六 结论,对系统开发的总结,设计的亮点,存在的不足,需要改进的地方 系统的开发涉及到各种类和函数的关联,虽然本次作业的要求较为简单,但作为初学者,我还是不那么得心应手。设计的亮点:1. 按照要求,此次的新闻管理系统我们至少要写两个类,一个时间Date类,一个时间News类。新闻是一个整体,想要管理新闻新闻的话是需要一整则新闻进行,所以,在News类中书写管理的功能函数会使得过程十分的棘手,所以,我就采用第三个类,管理类Management;在定义一个容器vector<News>使得操作大大的简化。2. 在对新闻按照要求格式进行输出并储存到文本文件中时,在每个数据成员前面都会加上说明符;如date:2012/2/2; ID:15等等,像这样的格式无论是输出到文本还是屏幕都只能使用string类的对象类操作。在后面的功能函数中我们又必须将其转化为数字,然后才能进行各种运算,这样会很麻烦。所以我在开始的时候就将其分开,不让他们成为一个整体,这样将不会在后面进行转换,具体过程见源代码。3. 再设计show()函数时,这里我们需要考虑的是是输出文本中的内容还是vector容器中的内容。输出文本中的内容这个函数只能使用一次,而输出vector中的内容则可以多次。所以,我采用了第二种。存在的不足: 作为一个新手,我对于代码的驾驭能力还是不够,不能灵活应用。比如对于应用和指针的应用,对于循环的应用。在这里面,最需要说的对于循环的应用,当然,简单的循环我还是会,但遇到复杂的循环就存在各种问题。如,在对加减法进行重载的时候,刚开始,我没有想到使用数组后循环加判断,这样问题就十分的简单,但我却只使用if条件判断,造成过程超级繁琐,过程超级麻烦,代码十分冗长。后来,我修改了加法的重载,但减法还是没有修改。对于数组的应用也存在不熟练的问题,比如getDayssofYear(); /返回一个日期在当年中的天数。这一个函数的设计本来是十分简单的,先使用一个数据,在其中写入每个月的天数,在二月份加入一个判断就行,然后用一个for(int i=1;i<m_month;i+)循环将所有的月份的值加起来;最后加上m_day的值结束;而我却使用了if判断嵌套循环;考虑的情况十分多不说,好容易出错。 对于关键词查找,我也是一带而过,不知应该怎么办。如果使用find()函数查找的话,这样就不叫关键词查找了,而如果要提前写好关键词的话,这样工作量也就太大了吧,而且还要考虑各种相近的近义词等等。所以对于这个我也是存在一定问题的。七 附录程序源代码,关键代码要做注释*mian函数*#include"management.h"int main()cout << "*" << endl;cout << "*欢迎进入新闻信息管理系统*" << endl;cout << "*" << endl;int i = 0; Management m; Date n;m.input(); m.identifier();while (i != 10)cout << 'n' << "请输入你想要进行的功能前所对应的数字" << endl;cout << "1:对已实现自动编号且自动按照要求格式储存的新闻输出" << endl;cout << "2:输出某类型新闻在某段时间内发生的次数" << endl;cout << "3:根据特定的关键词搜索新闻" << endl;cout << "4:统计每条新闻的字数" << endl;cout << "5:增加或删减新闻" << endl;cout << "6:输出某日期后一段日期报道的新闻" << endl;cout << "7:计算两个日期相差的时间" << endl;cout << "8:某个日期加上输入天数后的日期" << endl;cout << "9:比较两日期的大小" << endl;cout << "10:结束" << endl;cin >> i;if (i<1 | i>10)cout << "你输入的指令是错误的,请重新选选择并输入" << endl;switch (i)case 1:m.show(); break;case 2:m.lookUp(); break;case 3:m.find(); break;case 4:m.statistics(); break;case 5:m.change(); break;case 6:m.play(); break;case 7:n.decrease(); break;case 8:n.increase(); break;case 9:n.contrast(); break;case 10:break;system("pause");return 0;*Date类头文件*#ifndef DATE_H#define DATE_H#include <iostream>#include<cmath>using namespace std;class Dateprivate:int m_year, m_month, m_day;int m_totalDaysYear;public:Date(int d = 1, int m = 1, int y = 2001); /默认构造函数Date & operator=(const Date & d); /重载赋值运算符Date(); /析构函数int getDayssofYear(); /返回一个日期在当年中的天数int getRemainingDaysofYear(); /返回一个日期在当年中的余下的天数int compare(const Date & date); /比较date和当前对象的大小;返回1,0,-1,代表大于,等于,小于。int operator-(const Date & date); /计算并返回date和当前调用对象相差的天数Date operator+(int days); /计算并返回当前对象加上days天数的日期friend ostream & operator<<(ostream & out, const Date & date); /按照 年/月/日的格式输出friend istream & operator>>(istream & is, Date & date);inline bool isleapYear(); /内联函数,判断year是否为闰年int & getYear();int & getMonth();int & getDay();int & getTotalDaysYear();bool operator>=(const Date & date);bool operator<=(const Date & date);void increase();/调用“+”函数void decrease();/调用“-”函数void contrast();/调用compare()函数#endif*Date类源文件*#include"date.h"int a = 1, b = 0, c = -1;int y = -1;int & Date:getYear()return m_year;int & Date:getMonth()return m_month;int & Date:getDay()return m_day;int & Date:getTotalDaysYear()return m_totalDaysYear;Date:Date(int d,int m,int y)m_day = d; m_month = m; m_year = y;Date:Date()Date & Date:operator=(const Date & d)m_day = d.m_day; m_month = d.m_month; m_year = d.m_year;return *this;int Date:getDayssofYear()if (m_month > 2) if (m_month < 8) if (m_month = 3) y = 30 * 2 + m_day; if (3 < m_month && m_month <7 ) y = (m_month - 1) * 30 + 1 + m_day; if (7 <= m_month) y = (m_month - 1) * 30 + 2 + m_day; else if (m_month = 8) y = 30 * 7 + 3 + m_day; if (8 < m_month && m_month <= 10) y = (m_month - 1) * 30 + 4 + m_day; if (m_month > 10) y = (m_month - 1) * 30 + 5 + m_day;if (!isleapYear()y-;elsey = (m_month - 1) * 31 + m_day;return y;int Date:getRemainingDaysofYear()int a = getDayssofYear();if (isleapYear()y = 366 - a;else y = 365 - getDayssofYear();return y;int Date:compare(const Date & date)Date d = date;if (getYear() != d.getYear()if (getYear() > d.getYear()return a;if (getYear() < d.getYear()return c;else int m = getDayssofYear(), n = d.getDayssofYear();if (m>n)return a;if (m=n)return b;if (m<n)return c;int Date:operator-(const Date & date)Date d = date; int a = 0;int m = getYear(), n = d.getYear();if (getYear()> d.getYear()for (n; n < m; n+)if (n % 4 = 0 && n % 100 != 0 | n % 400 = 0 ? 1 : 0)a+;y = (m_year - d.m_year - 1) * 365 + a + d.getRemainingDaysofYear() + getDayssofYear();if (getYear() < d.getYear()for (m; m < n; m+)if (m % 4 = 0 && m % 100 != 0 | m % 400 = 0 ? 1 : 0)a+;y = (d.m_year - m_year - 1) * 365 + a + getRemainingDaysofYear() + d.getDayssofYear();if (getYear() = d.getYear()double a = getDayssofYear(), b = d.getDayssofYear();y = fabs(a - b);return y;Date Date:operator+(int days)int a = 0;int m12 = 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ;while (1)if (isleapYear()m1 = 29;elsem1 = 28;if (m_day + days > mm_month - 1)if (a = 0)days = days - (mm_month - 1 - m_day)-1;m_day = 1;if (a > 0)days = days - mm_month - 1;a+;m_month+;if (m_month > 12)m_year+;m_month -= 12;if (m_day + days <= mm_month - 1)m_day += days;break;return *this;ostream & operator<<(ostream & out,const Date & date)out << date.m_year << "年" << date.m_month << "月" << date.m_day << "日" << endl;return out;istream & operator>>(istream & is, Date & date)is >> date.getYear() >> date.getMonth() >> date.getDay();if (!is)cout << "输入失败" << endl;return is;inline bool Date:isleapYear()return m_year % 4= 0 && m_year % 100 != 0 | m_year % 400 = 0 ? 1 : 0;void Date:increase()while (1)int x = 0; Date d;cout << "请输入日期和天数" << endl;cin >> d >> x;cout <<"计算结果为:"<< (d + x) << endl;cout << "你是否想要继续进行?(是:请输入y,否:请输入n)" << endl;char c; cin >> c;if (c = 'n')break;bool Date:operator<=(const Date & date)if (m_year = date.m_year)if (m_month = date.m_month)return m_day <= date.m_day ? 1 : 0;elsereturn m_month <= date.m_month ? 1 : 0;elsereturn m_year <= date.m_year ? 1 : 0;bool Date:operator>=(const Date & date)if (m_year = date.m_year)if (m_month = date.m_month)return m_day >= date.m_day ? 1 : 0;elsereturn m_month >= date.m_month ? 1 : 0;elsereturn m_year >= date.m_year ? 1 : 0;void Date:decrease()while (1)cout << "请输入你想要计算的两个日期" << endl;Date a, b;cin >> a >> b;cout << "两日期相差天数为:" << (a - b) << endl;cout << "你是否想要继续进行?(是:请输入y,否:请输入n)" << endl;char c; cin >> c;if (c = 'n')break;void Date:contrast()while (1)cout << "请输入你想要比较的两个日期(大于输出:1,等于输出:0,小于输出:-1)" << endl;Date a, b;cin >> a >> b;cout<<"比较结果为:" << (pare(b) << endl;cout << "你是否想要继续进行?(是:请输入y,否:请输入n)" << endl;char c; cin >> c;if (c = 'n')break;*News类头文件*#ifndef NEWS_H#define NEWS_H#include <string>#include "date.h"class Newsprivate:Date m_date;int m_order;string m_type, m_content, m_place, m_title;public:int & getOrder();string & getType();string & getContent();string & getPalce();string & getTitle();Date & getDate();News(int o = 0, string t = "*", string c = "*", string p = "*", string tl = "*");News operator=(const News & n);/重载复制符号#endif*News类源文件*#include "news.h"News:News(int o, string t, string tl, string c, string p)m_order = o; m_type = t; m_title = tl; m_content = c; m_place = p;int & News:getOrder()return m_order;string & News:getContent()return m_content;string & News:getPalce()return m_place;string & News:getType()return m_type;string & News:getTitle()return m_title;Date & News:getDate()return m_date;News News:operator=(const News & n)m_type = n.m_type; m_title = n.m_title; m_place = n.m_place;m_date = n.m_date; m_content = n.m_content;return *this;*Management类头文件*#ifndef MANAGEMENT_H#define MANAGEMENT_H#include"news.h"#include<fstream>#include<vector>#include<iomanip>class Managementprivate:vector<News> stu;public:void input();/从文本中读入数据并输出到屏幕void show();/将信息显示在屏幕上 void identifier();/对新闻进行编号void store();/对新闻进行特定格式的储存void lookUp();/计算某段时间内某种类型新闻发生的次数void find();/根据关键词查找新闻void statistics();/统计新闻字数(包括标题,不包括地点、类型和时间)void change();/增减新闻void play();/输出某日期之后一段天数的新闻void s & a, News & b);/交换容器中两个元素的位置#endif*Management类源文件*#include "management.h"void Management:input()News n;ifstream f;f.open("news1.txt");if (!f)cout << "不存在的文件" << endl;while (!stu.empty()stu.pop_back();while (!f.eof()f >> n.getType() >> n.getTitle() >> n.getPalce() >> n.getDate() >> n.getContent(