类图
整个程序实际上主要只有Expression类,其中的部分功能依赖于Fraction类完成,而程序里其他无法实例化或实例化后无意义的部分,放在了assistant_functions文件中,起到辅助和扩展功能的作用。
assistant_functions文件中无法实例化或实例化后无意义的部分主要是指读入文件、输出文件和调用语言资源三部分。我觉得作为类,其首先是要能够实例化的,也就是可以成为一个对象。而读入和输出作为一种行为,其不具有对象的特征,并且我也不认为把读入和输出封装起来是一个好的做法,所以在程序中,我把具有共性的读入输出部分写成了函数,放在单独的文件中。
语言资源部分也一样,程序中更强调从主函数根据用户输入去主动调用资源数据,而不像是语言类自身所具有的的行为。并且语言作为一个类有些抽象了,我觉得更像一个基类,不适合放相互间差异性较大的属性和方法。
类和文件在设计、命名时都遵守了制定的编码规范,关于前缀的细则之后会在之前的命名规范继续补充。
接下来具体描述各个类和文件具有的属性和行为:
Expression:
属性:
- -m_expressionUint: vector
- -m_infix: string
- -m_postfix[kMax]: char
行为:
- +Expression()
- +RandomOperation(char ifMultiplyDivide): char
- +GenerateInfixExpression(int low, int high, int parameterNumber, char ifMultiplyDivide, char ifFraction, char ifBracket): string
- +TransferInfixIntoPostfix(): void
- +CalculateResult(): string
- +IsOnly(string expression): bool
Fraction:
属性:
- -m_nnumerator: int
- -m_ndenominator: int
- -m_snumerator: string
- -m_sdenominator: string
行为:
- +Fraction()
- +GetFraction(int l, int h): void
- +isDivisorZero(): bool
- +IsInt(): bool
- +TransferIntIntoFraction(int up, int down): void
- +Simplify(): void
- +TransferIntoStringNoInt(): string
- +TransferIntoString(): string
- +operator +(Fraction frac1, Fraction frac2): friend const Fraction
- +operator -(Fraction frac1, Fraction frac2): friend const Fraction
- +operator *(Fraction frac1, Fraction frac2): friend const Fraction
- +operator /(Fraction frac1, Fraction frac2): friend const Fraction
assistant_functions:
函数:
- +Max(int x, int y): int
- +Min(int x, int y): int
- +int GreatestCommonDivisor(int x, int y): int
- +RandomNumber(int down, int up): int
- +MatchLanguage(char language[]): bool
- +ReadFile(char *fileName): int
- +WriteFile(char *fileName, int idValue): void
- +PrintFinalResult(char *fileName, int correct, int wrong): void
代码实现(头文件)
由于.cpp定义部分太长,这里只贴出头文件声明部分。
/*expression.h 类声明部分*/
class Expression
{
private:
vector<string> m_expressionUint;
string m_infix;
char m_postfix[kMax];
public:
Expression();
char RandomOperation(char ifMultiplyDivide);
string GenerateInfixExpression(int low, int high, int parameterNumber, char ifMultiplyDivide, char ifFraction, char ifBracket);
void TransferInfixIntoPostfix();
string CalculateResult();
bool IsOnly(string expression);
};
/*fraction.h 类声明部分*/
class Fraction
{
private:
int m_nnumerator;
int m_ndenominator;
string m_snumerator;
string m_sdenominator;
public:
Fraction();
void GetFraction(int l, int h);
bool isDivisorZero();
bool IsInt();
void TransferIntIntoFraction(int up, int down);
void Simplify();
string TransferIntoStringNoInt();
string TransferIntoString();
friend const Fraction operator +(Fraction frac1, Fraction frac2);
friend const Fraction operator -(Fraction frac1, Fraction frac2);
friend const Fraction operator *(Fraction frac1, Fraction frac2);
friend const Fraction operator /(Fraction frac1, Fraction frac2);
};
/*assistant_functions.h 函数声明部分*/
int Max(int x, int y);
int Min(int x, int y);
int GreatestCommonDivisor(int x, int y);
int RandomNumber(int down, int up);
bool MatchLanguage(char language[]);
int ReadFile(char *fileName);
void WriteFile(char *fileName, int idValue);
void PrintFinalResult(char *fileName, int correct, int wrong);
类中的协作与信息传递(序列图)
这里用UML序列图来表现类之间的信息传递。下面作一定的文字说明:
分数类主要负责生成、化简、转换、计算分数,而生成表达式和处理表达式则由表达式类处理。表达式类和分数类为单向传递关系。表达式类并不向分数类传递信息,而是通过调用分数类中的某些方法来实现自己的功能职责,因而表达式类与分数类为依赖关系。
具体的信息传递过程如图中所示。表达式类在生成部分表达式时,若判断需要分数,则调用分数类,生成、化简分数,并转换为字符串存储,最后再判断表达式是否出现除零情况,以及得数是否为整数。在计算表达式时,将表达式中每一个参数都进行转换为分数,然后通过对分数的四则运算得出最后得数,最后再判断表达式是否出现除零情况,以及得数是否为整数。
程序实现思路(流程图)
该程序的实现思路如流程图所示。下面作大致描述:
主函数中,通过调用语言资源及读入用户数据,实现多语言切换。然后通过对表达式各项要求的询问和读入,循环生成出符合用户要求的表达式。每当成功生成一个表达式后,输出提供给用户进行计算,读入用户答案,并与计算出的正确得数进行比对,统计正误个数。当所有表达式生成结束后,输出统计结果。