C++课程设计——背单词程序
设计要求
设计一背单词程序,程序以菜单方式工作,字典使用文本文件存放就可以了。使之能提供以下功能:添加新词 支持顺序测验和随机测验 记录没背过的单词 查找单词的汉语或英语意思(输入中文查对应的英语意思,输入英文查对应的汉语意思)
目录
1.课程设计目的
1.1 前言
背英语单词是最令人头疼的事儿,如果能选择一套适合的背单词软件,对于单词记忆会有事半功倍的效果,然而目前市场上背单词软件到处都是,我们应该选择什么软件呢,这确实是件另人头疼的事,选到好的,对我们的学习也许有很大帮助。因此,设计了一款针对性的背单词程序,用户使用时可以根据自己的水平构造适合自己的词库。该程序设计了基本的增、删、改、查功能,在查询部分细分了4大类——英译汉、汉译英、浏览没背过的生词、浏览整个词典。
值得注意的是,该程序会按照英语词典顺序对用户录入的单词和翻译进行重新排列。比如:录入时的顺序时d,c,a,e。而用户再次浏览时的顺序是a,b,c,d。此外,用户可以利用程序的顺序测验功能进一步按照词典顺序进行背单词。用户可以利用随机测验功能进行单词考试(出题是系统随机出不同的题)。
1.2功能性需求分析
背单词程序包含了许多C++知识点,C++的特色就是类的运用。首先是先定义一个类来进行对数据成员和一系列成员函数进行声明定义,然后以菜单界面的方式来进行调用成员函数进行功能的实现。我对于这个项目构造了以下功能:
(1)添加单词 用户在输入英文后,还需要输入对应的翻译
(2)删除单词 用户输入想删除的英文,系统会把这个单词从文件里删除
(3)修改单词 当英文和对应的汉语不相符时,用户可以先输入该英文,再输入正确的其汉语
(4)顺序测验 用户进入该界面后,会按照词典的顺序进行记忆背诵单词,同时系统还会统计用户记忆了多少个单词
(5)随机测验 用户进入该界面后,会按照系统随机给出的5个选择题进行作答。用户需要对每道题进行选择A或B或C或D,答题完毕后,系统会给出分数和评估用户的成绩是否合格,是否优秀。
(6)查看词典 用户如果选择5,会进入二级菜单(1.英译汉 2.汉译英3.浏览全部4.查看未背过的单词)。针对英译汉,用户输入英文,系统会自动给出该英文对应的汉语意思,汉译英同理。当用户查看未背过的单词时,需要用户输入已经记住的单词个数,再输入想查看的生单词个数。
(7)退出系统 当用户输入7,就会退出背单词程序
1.3 非功能性需求分析
为用户提供更好的使用感受,对程序进行美化:
(1)调用了EaxyX图形库,创建了一个窗口,同时显示它的控制台。
(2)使用了system(“color F5”);显示颜色控制函数,设置字体(前景色)和背景颜色,详细颜色设置说明如图1-1。F代表背景色黑色,5代表字体颜色。
图1-1 详细颜色设置说明
(3)运行界面友好,易于操作,输入方式简单明了易于操作、安全可靠。
(4)对输入错误的情况进行提示。
(5)背单词针对的是英语,所以单词信息包括英文和对应的翻译
string english;
string chinese;
2.课程设计题目描述和要求
2.1概要设计
1.本程序所要实现的基本功能有添加单词、查看生词、英译汉、汉译英、顺序测验、随机测验。另外设计了删除单词、修改单词、浏览全部单词便于对文件里的数据进行完善。
2.设计针对特定功能的数据结构和类:
WordS类存放单词的英文和中文,整个词库则使用STL中的vector向量来存储,即将存在文件里的单词数据转存到vector容器中。
Data类中声明和实现对单词的操作——增、删、改、查、统计、判断是否合规。
MyFrame类中声明和实现在菜单中的功能。
Myless类实现辅助排序功能。
在本设计中为了保持每个类的功能清晰、简洁,在单个类内部实现的功能应当有一定的联系,非对外的接口设置为private属性;
3.程序的具体实现,涉及的算法主要包括二分法查找单词、词库排序
2.2程序设计组成框图
程序设计组成框图如图2-1所示
图2-1背单词程序组成框图
2.3 背单词程序流程图
背单词流程图,如图2-2所示
图2-2 背单词流程图
2.4类图
1.Data类图如图2-4-1所示
图2-4-1 Data类图
2.MyFrame类图如图2-4-2所示
图2-4-2 MyFrame类图
3.WordS类图如图2-4-3所示
图2-4-3 WordS类图
4.myless类图如图2-4-4所示
图2-4-4 myless类图
3.课程设计报告内容
3.1详细设计
3.1.1定义一个WordS类
WordS类用来表示每一个单词的信息内容——有英语单词和对应的中文翻译两个内容,用两个私有数据成员来进行表示:
private:
string english; //英文单词
string chinese; //对应的中文翻译
同时为了方便其他类对单词的内容进行操作,还提供了一系列比较简单基础的公有操作:
public:
WordS();//默认空构造函数
WordS(string english, string chinese); //给出英文单词和中文解释的构造函数
string getEnglish();//获取英文内容
string getChinese();//获取中文内容
void setEnglish(string english); //重新设置英文内容
void setChinese(string chinese); //重新设置中文内容
3.1.2定义一个Data类
Data类是一个存放数据的类,用来储存录入的单词的信息内容,并把所有单词包含的内容放在一个vector<WordS>中(Vector容器的详细解释见附录),该数据段被定义为private。
private:
vector<WordS> words; //存放单词,向量内的元素为WordS类对象
WordS wordNode;//vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
//(可以理解为动态数组,是封装好了的类)
//进行vector操作前应添加头文件#include <vector>
//定义具有10个WordS元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定//vector<WordS>a(10);
另外提供对外的接口,可以对单词表进行一系列操作:
public:
Data();//默认构造函数
int getDicSize();//返回单词的总数目
bool isEmpty();//判断字典是否为空
WordS getWordNode(int i); //返回下标为i的单词,i不合法则返回空
int setWordNode(int i, WordS newWordNode); //修改第i个WordS节点,失败则返回值为负数
int addWordNode(WordS wordNode); //添加一个新单词
int deleteWordNode(int i); //删除第i个WordS节点,失败则返回值为负数
int binarySearch(string word); //根据单词二分查找相应的条目,查找失败返回负数
int binarySearchr(string word); //根据单词二分查找相应的条目,查找失败返回负数
void sortWords(); //重新对单词按字典序进行排序
3.1.3定义一个myless类
myless类是为了方便调用sort()函数,重载()运算符,保证录入文件里的单词是按照词典顺序来排列的,参数是两个WordS类的对象。
public:
bool operator()(WordS a, WordS b) {
//重载运算符,为排序做准备
return a.getEnglish() < b.getEnglish();//按照字典序排列 按照字母顺序//return 1 > 2; 返回false
}
3.1.4定义一个MyFrame类
MyFrame类主要控制系统的界面,有一个Date类的实例dateBase作为私有的数据成员,用来保存所有单词的内容数据。
private: Data dataBase; //相关的内容数据库
同时MyFrame类提供了一系列公有方法来实现与背单词相关的功能。如下:
public:
MyFrame();//空构造函数
void initialize();//初始化整个界面
void addWord();//添加新单词
void deleteWord();//删除已有的单词
void modifyWord();//修改现有的单词
void browseDic(); //浏览词典
void exitSystem();//退出系统
void exam();//模拟考试
void exercise();//背单词练习
void konghang(int n); //控制格式,输出一些空行
3.1.4 main()函数
在main()函数里面主要调用了EaxyX库用来对程序进行美化,如下:
initgraph(640,450,SHOWCONSOLE);//创建一个窗口 显示控制台
setbkcolor(BROWN);//背景颜色为棕色1
cleardevice();//清屏2
settextstyle(50,0,L"楷体");//设置文字样式,大小,字体
setbkmode(TRANSPARENT);//设置背景模式trans parent透明
settextcolor(RGB(34,633,82));
outtextxy(50, 50, L"欢迎使用背单词小程序");
MyFrame frame;//生成一个界面对象
frame.initialize();//初始化界面并将控制转移到该对象内部
getchar();//使窗口停留
closegraph();//关闭窗口
3.1.6主要功能
1.单词表的实现
在Data类的构造函数中借助ifstream实现构建单词表的功能。首先实例化一个ifstream类,然后打开文件,读入相应的单词记录同时实例化一个WordS类,最后将该对象放入vector容器中并关闭文件:
ifstream file("dicA.txt");//打开文件
while (file >> english >> chinese) {
this->wordNode.setChinese(chinese);
this->wordNode.setEnglish(english);
(this->words).push_back(this->wordNode); //words表示实例化一个WordS类,wordNode表示单词信息(英文+中文)
}
file.close();//关闭文件
2.增、删、改功能的实现
增加单词由Data类中的addWordNode(WordS wordNode)函数实现,首先放到容器vector中,再进行重新排序:
int Data::addWordNode(WordS wordNode) {
this->words.push_back(wordNode);
//在 words尾部添加wordNode
//vector<WordS> words;
// words.push_back(wordNode);
this->sortWords();
return 0;
}
删除节点,首先需要根据给出的单词进行二分查找,然后通过Data类中的deleteWordNode(int i)函数来实现,二分查找的基本原理是利用序列的有序性,每次将查找范围折半,直到确定找到目标或者目标不存在:
//删除第i个WordNode节点,失败则返回值为负数
int Data::deleteWordNode(int i) {
if ((i < 0) || (i >= (int)(this->words.size()))) {
//cout<<"下标不合法!"<<endl;
return -1;
}
this->words.erase((this->words.begin()) + i);
return 1;
}
//根据单词二分查找相应的条目,查找失败返回空
int Data::binarySearch(string word) {
int left = 0;
int right = this->getDicSize() - 1; //进行二分查找
while (left <= right) {
int middle = (left + right) / 2; //中间元素
if (this->words[middle].getEnglish() == word) //找到目标
return middle;
else if (this->words[middle].getEnglish() > word) //目标在左半部分
right = middle - 1;
else left = middle + 1; //目标在右半部分
}
return -1;
//cout<<"查找失败!"<<endl;
//return *(new WordNode());
}
修改单词的功能也只需找到对应的英文,然后修改翻译部分的中文内容,由于单词的内容没有发生变化,因此不需要重新排序。
//修改第i个WordNode节点,失败则返回值为负数
int Data::setWordNode(int i, WordS newWordNode) {
if ((i < 0) || (i >= this->getDicSize())) {
//cout<<"下标不合法!"<<endl;
return -1;
}
this->words[i] = newWordNode;
this->sortWords();
return 1;
}
3.顺序测验、随机测验、浏览没背过的单词
(1)在按顺序背单词的界面实现了顺序测验,此时的顺序并非录入的顺序,是按照词典顺序进行背诵,对背诵的单词进行计数的目的是为了浏览没背过的单词。
核心代码如下:
int number = this->dataBase.getDicSize();//统计单词表中所有的单词个数
for (int i = 0; i < number; i++) {
cout << "单词: " << this->dataBase.getWordNode(i).getEnglish() << endl;
cout << endl;//按照单词下标找出单词对应的在中文和英文
cout << "解释: " << this->dataBase.getWordNode(i).getChinese() << endl;
cout << "按照单词表顺序,你已经记住的单词数:" << i+1 <<endl;
(2)在模拟考试的界面实现了随机测验,生成随机数取出相应单词呈现给用户,核心代码如下:
srand(unsigned(time(0))); //防止每次运行生成的随机数相同
for (int i = 0; i < 5; i++) {
//修改练习题目,随机选取5个单词
int tmp = rand() % (this->dataBase.getDicSize());
bool repeat = false;
for (int j = 0; j < i; j++) {
//检查随机生成的单词是否重复
if (number[j] == tmp)
repeat = true;
}
if (repeat == true)
i--;
else
number[i] = tmp;
}
(3)浏览没背过的单词,详细代码如下:
else if (order ==