现代软件工程 第一章 【概论】第1题——孙雪莹、张功
第一步: 像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 “软件”, 分别满足下面的各种需求。下面这些需求都可以用命令行参数的形式来指定:
a) 除了整数以外,还要支持真分数的四则运算。 (例如: 1/6 + 1/8 = 7/24)
b) 让程序能接受用户输入答案,并判定对错。 最后给出总共 对/错 的数量。
c) 逐步扩展功能和可以支持的表达式类型,最后希望能支持下面类型的题目 (最多 10 个运算符,括号的数量不限制):
我们首先的想法是将整数和分数统一,建立一个数类number。它包含分子和分母,当数是整数的时候,分母为1,这样便于后面运算的进行。这样我们就减少了一种除法运算,只剩下加法、减法和乘法。我们定义在类中的公有函数里。这样以后我们计算的单位就变成了类。
class number{ private: int numerator;//分子 int denominator;//分母 public: number(){} number(int a){ numerator = a; denominator = 1; } number(int a, int b){ numerator = a; denominator = b; } void prin_number(){ if (numerator == 0) { printf("0"); } else{ if (denominator == 1){ printf("%d", numerator); } else{ printf("%d/%d", numerator, denominator); } } } number plus(number n1, number n2){ number re; int divisor;//最大公约数 re.denominator = n1.denominator * n2.denominator; re.numerator = n1.numerator * n2.denominator + n2.numerator * n1.denominator; divisor = greatest_common_divisor(re.denominator, re.numerator); re.denominator = re.denominator / divisor; re.numerator = re.numerator / divisor; return re; } number minus(number n1, number n2){ number re; int divisor;//最大公约数 re.denominator = n1.denominator * n2.denominator; re.numerator = n1.numerator * n2.denominator - n2.numerator * n1.denominator; if (re.numerator != 0){ divisor = greatest_common_divisor(re.denominator, re.numerator); re.denominator = re.denominator / divisor; re.numerator = re.numerator / divisor; } return re; } number mul(number n1, number n2){ number re; int divisor;//最大公约数 re.denominator = n1.denominator * n2.denominator; re.numerator = n1.numerator * n2.numerator; if (re.numerator != 0){ divisor = greatest_common_divisor(re.denominator, re.numerator); re.denominator = re.denominator / divisor; re.numerator = re.numerator / divisor; } return re; } };
定义了类以后,我们知道四则运算的符号特别的多,于是我们这时候要使用“栈”这种数据结构。下面是“栈”数据结构的基本函数。
#include"stdafx.h" #include"iostream" using namespace std; #include"Caculating.h" #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define ERROR 0 #define OK 1 #define OVERFLOW -2 typedef number Status; typedef char SElemType; typedef struct{ SElemType * base; SElemType * top; SElemType stacksize; }SqStack; Status InitStack(SqStack & S){ S.base = new SElemType[STACK_INIT_SIZE]; if (!S.base){ return ERROR; } S.top = S.base; S.stacksize = STACK_INIT_SIZE; return OK; } Status GetTop(SqStack S, SElemType &e){ if (S.top == S.base)return ERROR; e = *(S.top - 1); return OK; } Status Push(SqStack & S, SElemType e){ if (S.top - S.base >= S.stacksize){ S.base = new SElemType[STACK_INIT_SIZE + STACKINCREMENT]; if (!S.base)return OVERFLOW; S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; } *S.top++ = e; return OK; } Status Pop(SqStack & S){ SElemType e; if (S.top == S.base)return ERROR; e = *--S.top; return e; } Status Print(SqStack S){ SElemType *p = S.top; while (p != S.base){ cout << *--p; } cout << endl; return OK; } Status Destroy(SqStack &S){ delete S.base; S.top = NULL; S.base = NULL; S.stacksize = 0; return OK; }
之后我们要借助两个栈来进行运算,一个栈是数栈,另一个是符号栈。这时,我们首先要定义符号的优先级。
int Judgement(char ch){ switch (ch){ case'#':return 0; break; case'+':case'-':return 1; break; case'*':return 2; break; case'/':return 3; break; case')':return 4; break; case'(':return 5; break; default:return 6; break; } }