- 实验目的
本次实验要求使用“类”相关机制来设计并实现一些程序,以熟悉 C++提供的面向对象基本概念和机制,掌握数据抽象的基本手段,用类型上的操作来封装数据结构,为面向对象程序设计奠定基础。
- 实验环境
操作系统:win10
开发工具:Visual Studio2015
- 实验内容
题目一:
Complete and test Date. Reimplement it with ‘‘number of days after 1/1/1970’’ representation.
类型 Date 是第十章的讲解用例,在第2次实验中存在类似的实验。书本中对日期的三个要素-日、月、年先使用三个int整数分别表示,10.3节又用enum Month作为月份的类型。
这个练习要求:首先按照教材第十章介绍的知识定义/实现该类型的所有特征(数据结构和操作),并进行一些测试工作。教材中已经指出了日期上的操作集,你也可以对操作集扩充。
题目二:
Rewrite Tnode from §7.10[7] as a class with constructors, destructors, etc.
Define a tree of Tnodes as a class with constructors, destructors, etc.
在 class Tnode{…}中,除了已给定的数据成员外,还应将当时要求完成的几个操作函数改写为这个class的成员函数,包括构造函数(初始化结点)、析构函数(释放该结点的数据)、访问树结点的几个操作等。
再定义一个类型 class Tree(类名自定),表示“二叉树”这一概念,该树的所有结点的类型为class Tnode。
题目三:
Define a class for analyzing, storing, evaluating, and printing simple arithmetic expressions consisting of integer constants and the operators +, -, *, and /. The public interface should look like this:
class Expr {
// …
public:
Expr(char*);
int eval();
void print();
};
The string argument for the constructor Expr::Expr() is the expression. The function Expr::eval() returns the value of the expression, and Expr::print() prints a representation of the expression on cout . A program might look like this:
Expr x("123/4+123*43");
cout << "x = " << x.eval() << "\ n ";
x.print();
本题实际上是第六章给出的桌面计算器的变形——将原来的全局变量、全局函数使用 class Expr{ … }; 封装起来,抽象为一个类型。这样程序运行过程中,就允许同时存在多个计算器对象了。
- 实验步骤
题目一:
实验思路:程序包含三个文件,分别是定义类DATE的date.hpp、实现DATE类的date.cpp和测试的test.cpp。思路如下:保持 课本对Date 类型公布的对外接口不变,将日、月、年三个要素仅使用一个整数N表示,N表示从1970年1月1日开始的天数。使用 set_default()和 static Date default_date、配合构造函数实现了日期的缺省初始值。main函数获取输入的一个日期,然后经过程序计算后输出距离1970.1.1的天数。
数据结构定义和类的接口定义:
class Date
{
int d, m, y;
static Date default_date;
public:
enum Month { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
class Bad_date { };
Date(int dd = 0, Month mm = Month(0), int yy = 0);
int day() const;
Month month() const;
int year() const;
/* … */
static void set_default(int, Month, int);
Date& add_year(int n);
Date& add_month(int n);
Date& add_day(int n);
/* ... */
int leapyear(int);
};
实验源码
西电软工oop上机题目410.6-2.rar-C++文档类资源-优快云下载
问题:输入日期如果在1970.1.1之前的话,程序无法正常运行得出正常结果。
解决方案:加入一个判断,判断如果输入日期在1970.1.1之前的话,将输入日期赋值给初始日期,1970.1.1当作输入日期,计算出结果后再加上负号即可得出结果。
题目二:
实验思路:首先定义实现结点的类,然后有多个结点构成一个树的类,在main函数中获取树的各个结点的内容,对每个输入的单词进行判断是否已存在,然后插入相应的节点上。程序最后先序遍历和中序遍历输出树的所有信息,然后销毁树。
数据结构定义和类的接口定义:
class Tnode {
public:
Tnode(const char* = 0);
Tnode(const std::string&);
virtual ~Tnode();
void print(std::ostream& outFile) const;
public:
void setWord(const std::string& val) { word = val; }
const std::string& getWord() const { return word; }
std::string& getWord() { return word; }
void setLeft(Tnode* val) { left = val; }
const Tnode* getLeft() const { return left; }
Tnode*& getLeft() { return left; }
void setRight(Tnode* val) { right = val; }
const Tnode* getRight() const { return right; }
Tnode*& getRight() { return right; }
void setCount(int val) { count = val; }
int getCount() const { return count; }
int& getCount() { return count; }
private:
Tnode(const Tnode&);
Tnode& operator=(const Tnode&);
private:
std::string word;
int count;
Tnode* left;
Tnode* right;
};
class BSTree {
public: // public interface for operations
BSTree();
virtual ~BSTree();
bool regist(const std::string& newWord);
bool regist(const char* newWord);
void print(std::ostream& outFile);
void print_byorder(std::ostream& outFile);
private:
BSTree(const BSTree&);
BSTree& operator=(const BSTree&);
private:
Tnode* myRoot;
};
实验源码:
https://download.youkuaiyun.com/download/weixin_52552833/87229387
问题和解决方案:无
题目三:
实验思路:采用多个头文件、多个源文件的方式实现完整程序,分号或回车,认为一个表达式结束,并记作一行,在处理过程中累计行数;当输入的内容不符合算式语法规定时,提示错误原因并且提示相应的出错行。
数据结构定义和类的接口定义:
class SyntaxTree
{
Token_value opCode;
std::string mText;
SyntaxTree* myLeft;
SyntaxTree* myRight;
Expr* myOwner;
public:
SyntaxTree(Expr* owner, Token_value tok, const std::string& txt,
SyntaxTree* left = NULL, SyntaxTree* right = NULL);
~SyntaxTree();
double eval();
void printPostfix(std::string & retValue);
void printPrefix(std::string & retValue);
void printParenthesized(std::string & retValue); };
class Expr{
public:
Expr();
Expr(const char* strExpr);
virtual ~Expr();
const std::string& getText() const{
return mText;
}
bool setText(const char* strExpr);
double eval();
std::string printPostfix();
std::string printPrefix();
std::string printParenthesized();
std::string getError() const;
void setError(const char* msg, const char* leftExpr);
CSymbolTable& getSymTbl(){
return table;
}
private:
std::string mText;
CSymbolTable table;
SyntaxTree* myTree;
std::string errMessage;
};
实验源码
https://download.youkuaiyun.com/download/weixin_52552833/87229391
问题和解决方案:c++的sstream流的运用,可以从中分别读出运算式子的数字与字符还有去除括号时将未处理字符(即非括号内的字符)以及括号内的子式处理结果输出到流中,便于迭代去除括号。
- 实验结果
题目一
输入:1970 1 20
输出:19
输入:1980 3 1
输出:3712
输入:2017 1 1
输出:17167
题目二
输入:a b c ab abc ab aa bb cc abc a c bc
输出:
Print tree by <先序遍历>:
a: 2
<NULL>
b: 1
ab: 2
aa: 1
abc: 2
c: 2
bb: 1
<NULL>
bc: 1
cc: 1
Print tree by <字典顺序-中序遍历>:
a: 2
aa: 1
ab: 2
abc: 2
b: 1
bb: 1
bc: 1
c: 2
cc: 1
题目三
输入:test_case("1+2", 3);
输出:
前缀 表达式:[+ 1 2]
后缀 表达式:[1 2 +]
加括弧表的达式:[((1)+(2))]
表达式的值:[3]
输入:test_case("pi+(a=1.0/.3*10", 0);
输出:
Your original expression is [pi+(a=1.0/.3*10]
O,表达式错了: 缺少右括弧, 在这里发现的:末尾.
- 实验总结
本次实验通过使用“类”相关机制来设计并实现一些程序,让我熟悉 C++提供的面向对象基本概念和机制,掌握数据抽象的基本手段,用类型上的操作来封装数据结构,为面向对象程序设计奠定基础。学习过程中,也学会了如何编程的思想。这次实验中我也出现过一些比较严重的错误。所以我们在学习新知识的时候也需要回顾一下已学知识,巩固基础,多多练习。