三、 结对的伙伴
买倩玉:【 https://www.cnblogs.com/maiqyBlog/】
编程思路:我们一开始决定使用C/C++,但是由于对C++掌握基础不够牢,最后决定使用python语言。在作业一中我也尝试使用了python语言但是没有写出来,所以从上次到现在也一直再学习python语言。
f4类 | 基于控制台的命令行输入,调用其它函数 |
createProblem类 | 生成随机表达式 |
calculate类 | 将中缀表达式转换成后缀表达式 |
五、重点和难点
arithList = []
for i in range(7):
if i % 2 == 0:
arithNum = random.randint(0, 9)
if len(arithList) > 1:
while (arithNum == 0) and arithList[len(arithList) - 1] == '/':
arithNum += random.randint(1,9)
arithList.append(arithNum)
else:
arithList.append(create.createOperator(self))
(2)随机算式的生成(功能二和功能三)
功能二、三里的运算符加上了括号。对于表达式,括号必须是成对出现,并且加在最外面的括号没有意义,经过讨论,我的结对搭档提出了如下处理方式:
def createBrackets(self, exp, operatorNum):
expression = []
if exp:
expLength = len(exp)
leftPosition = random.randint(0, int(operatorNum / 2))
rightPosition = random.randint(leftPosition + 1, int(operatorNum / 2) + 1)
mark = -1
for i in range(expLength):
if exp[i] in ['+', '-', '*', '/']:
expression.append(exp[i])
else:
mark += 1
if mark == leftPosition:
expression.append('(')
expression.append(exp[i])
elif mark == rightPosition:
expression.append(exp[i])
expression.append(')')
else:
expression.append(exp[i])
# 如果生成的括号表达式位置为第一个运算数的左侧与最后一个运算数的右侧,则重新生成
if expression[0] == '(' and expression[-1] == ')':
expression = self.createBrackets(exp, 4)
return expression
return expression
(3)无限小数的判断
对于无限小数的判断,查阅资料可知结论:将分数化为最简分数
后,分母的全部因数
(除去1和其自身)没有为2或5以外的数,则该分数就不是无限循环小数
;否则为无限循环小数。
所以一开始我是这样想的:利用python的fractions模块进行分数运算,然后将最终结果(分数)约分,利用上述结论判断是否是无限循环小数然后再进行输出。但是这个想法没有实现,我们最后直接暴力判断结果长度是否>20,如果>20,就使用round函数来保留小数点后三位小数(四舍五入)。
if len((str)(ansR)) > 20 :
if (float(ans1) == round((float)(ansR), 3)):
print("回答正确。")
rightAnswer += 1
else:
print("回答错误,正确答案是", round(ansR, 3))
wrongAnswer += 1
else:
if (float(ans1) == float(ansR)):
print("回答正确。")
rightAnswer += 1
else:
print("回答错误,正确答案是", ansR)
wrongAnswer += 1
还有一点是由于python语言不需要对变量进行数据类型的定义,所以在运算上我们使用了Decimal模块来进行精确浮点数运算。
def operate(self, number1, number2, operator):
number1 = Decimal(number1)
number2 = Decimal(number2)
if operator == '+':
return number2 + number1
if operator == '-':
return number2 - number1
if operator == '*':
return number2 * number1
if operator == '/':
return number2 / number1
(4)中缀表达式转换成后缀表达式(即逆波兰表达式)
def generatePostfixEpression(self, expression):
# 去除表达式空格
expression = expression.replace(' ', '')
# 创建运算符栈和表达式栈
operatorStack = list()
expressionStack = list()
for element in expression:
if element in self.operators:
if not operatorStack:
operatorStack.append(element)
else:
if element == ')':
for top in operatorStack[::-1]:
if top != '(':
expressionStack.append(top)
operatorStack.pop()
else:
operatorStack.pop()
break
else:
for top in operatorStack[::-1]:
# 左括号只有遇到右括号才出栈
if self.priority[top] >= self.priority[element] and top != '(':
expressionStack.append(top)
operatorStack.pop()
else:
operatorStack.append(element)
break
if not operatorStack:
operatorStack.append(element)
else:
expressionStack.append(element)
# 将操作符栈中的操作符入到表达式栈中
for i in range(len(operatorStack)):
expressionStack.append(operatorStack.pop())
return expressionStack
def calculate(self, expression):
# 后缀表达式生成
expressionResult = self.generatePostfixEpression(expression)
calcalateStack = list()
# 遍历后缀表达式
for element in expressionResult:
if element not in self.operators:
calcalateStack.append(element)
else:
number1 = calcalateStack.pop()
number2 = calcalateStack.pop()
result = self.operate(number1, number2, element)
calcalateStack.append(result)
return calcalateStack[0]
parser.add_option("-n", type="int", help='需要输入的题目个数(无括号)')
parser.add_option("-c", type="int", help='需要输入的题目个数(有括号)')
controlIn = input()
arg = controlIn.split( )
# print(arg)
# print(len(arg))
# print(arg[0])
# print(arg[1])
flag = 0
if len(arg) == 2:
if(arg[0] == '-n'):
flag = 1
elif(arg[0] == '-c'):
flag = 2
elif arg[0] == '-c' and arg[2] == '-f':
flag = 3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--num")
parser.add_argument("-c", "--cin")
parser.add_argument("-f", "--fil")
args = parser.parse_args()
if args.num != None :
f4().flag1(args.num)
if args.cin != None :
if args.fil == None :
f4().flag2(args.cin)
else:
f4().flag3(args.cin, args.fil)
在f4类里,分别定义了flag1、flag2、flag3函数分别实现功能一、功能二、功能三。用flag1举例如下:
def flag1(self, num1):
cl = calculator()
ca1 = create()
try:
num1 = int(num1)
rightAnswer = 0
wrongAnswer = 0
if isinstance(num1, int):
if num1 <= 0:
print("题目数量必须是 正整数。")
else:
for i in range(num1):
expList = ca1.createArithmetic(0)
print(expList)
print('?', end='')
ansR = cl.calculate(expList)
#print(ansR)
ans1 = input()
if len((str)(ansR)) > 20 :
if (float(ans1) == round((float)(ansR), 3)):
print("回答正确。")
rightAnswer += 1
else:
print("回答错误,正确答案是", round(ansR, 3))
wrongAnswer += 1
else:
if (float(ans1) == float(ansR)):
print("回答正确。")
rightAnswer += 1
else:
print("回答错误,正确答案是", ansR)
wrongAnswer += 1
print("总共" , num1 , "道题,你答对" , rightAnswer , "道题。")
else:
print("题目数量必须是 正整数。")
except:
print("题目数量必须是 正整数。")





功能二:
功能三:
我们在结对编程之前读了《构建之法》第四章两人合作这一部分知识,从领航员和驾驶员两个角色定位出发,为我们两个人的结对编程打下了基础。我觉得我们两个人没有绝对的领航员、驾驶员之分,更多的是相互领航、相互驾驶,达到了一个很好的沟通、合作效果。同时,在对方的身上也能学到很多东西。代码复审的时候,自己检查自己的真的查不出错,查别人的却很迅速,这可能就是“当局者迷,旁观者清”的另一种解释吧。

九、C/C++尝试记录
有点羞愧,C是自己接触的第一门语言,C++接触比较少但是作为算法、数据结构课程的常用语言也应该掌握。所以还是决定记录一下自己未完成的代码。希望有一天能够真正实现。
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#define maxsize 1024
using namespace std;
//获取运算符
char getOp()
{
char op[4] = {'+', '-', '*', '/'};
return op[rand()%(strlen(op))];
}
//获取运算数
float getNumber(int maxNum)
{
return rand()%maxNum+1;
}
//判断答案正误
void judgeAnswer(int s1, int s2, float a[2])
{
if (s2 == s1)
{
cout << "回答正确。" << endl;
a[0]++;
}
else
{
cout << "回答错误,正确答案是" << s1 << endl;
a[1]++;
}
}
//获取随机算式
string getExp()
{
int n = 3;
const int MAX = 10;
int expNum, len;
string str = "";
string temp;
for(int i = 0; i < 7; i++)
{
if((i % 2) == 0)
{
expNum = getNumber(MAX);
len = str.size();
while(str[len - 1] == '/' && expNum == 0 && len > 0)
expNum += 1;
stringstream str1;
str1 << expNum;
str1 >> temp;
str += temp;
}
else
{
str += getOp();
}
}
return str;
}
typedef struct
{
float data[maxsize];
int top;
}stack1;
typedef struct
{
char data[maxsize];
int top;
}stack2;
void initStack1(stack1 *s)
{
s = (stack1*)malloc(sizeof(stack1));
s->top = -1;
}
int push1(stack1 *s, float ch)
{
if (s->top == maxsize - 1)
return 0;
else
{
s->top++;
s->data[s->top] = ch;
return 1;
}
}
int pop1(stack1 *s, float ch)
{
if (s->top == -1)
printf("栈上溢出!\n");
else
ch = s->data[s->top];
s->top--;
return 1;
}
void initStack2(stack2 *s)
{
s = (stack2*)malloc(sizeof(stack2));
s->top = -1;
}
int push2(stack2 *s, char ch)
{
if (s->top == maxsize - 1)
return 0;
else
{
s->top++;
s->data[s->top] = ch;
return 1;
}
}
int pop2(stack2 *s, char ch)
{
if (s->top == -1)
printf("栈上溢出!\n");
else
ch = s->data[s->top];
s->top--;
return 1;
}
int isOp(char ch)
{
switch (ch)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':
return 1;
default:
return 0;
}
}
char prior[7][7] =
{
// '+' '-' '*' '/' '(' ')' '#'
/*'+'*/{ '>', '>', '<', '<', '<', '>', '>' },
/*'-'*/{ '>', '>', '<', '<', '<', '>', '>' },
/*'*'*/{ '>', '>', '>', '>', '<', '>', '>' },
/*'/'*/{ '>', '>', '>', '>', '<', '>', '>' },
/*'('*/{ '<', '<', '<', '<', '<', '=', '< '},
/*')'*/{ '>', '>', '>', '>', ' ', '>', '>' },
/*'#'*/{ '<', '<', '<', '<', '<', '> ', '=' },
};
int opId(char op1)
{
switch (op1)
{
case'+':return 0;
case'-':return 1;
case'*':return 2;
case'/':return 3;
case'(':return 4;
case')':return 5;
case'#':return 6;
default:return -123456;
}
}
char precede(char op1, char op2)
{
int a, b;
a = opId(op1);
b = opId(op2);
return(prior[a][b]);
}
float operation(float a, char op, float b)
{
switch (op)
{
case '+':
return b + a;
case '-':
return b - a;
case '*':
return b * a;
case '/':
return b / a;
default:
return -123456;
}
}
void createExpression(const char *exp)
{
if (exp == NULL)
{
exit(1);
}
string str2 = getExp();
cout<<str2;
exp = str2.data();
}
void transmitExpression(char *exp, char postexp[])
{
stack2 FZ;
initStack2(&FZ);
int i = 0;
char x;
FZ.top = -1;
push2(&FZ, '#');
FZ.data[FZ.top] = '#';
while (*exp != '\0')
{
if (!isOp(*exp))
{
while (*exp >= '0'&&*exp <= '9')
{
postexp[i++] = *exp;
exp++;
}
postexp[i++] = '#';
}
else
switch (precede(FZ.data[FZ.top], *exp))
{
case'<':
push2(&FZ, *exp);
exp++;
break;
case'=':
x = FZ.data[FZ.top];
pop2(&FZ, x);
exp++;
break;
case'>':
postexp[i++] = FZ.data[FZ.top];
x = FZ.data[FZ.top];
pop2(&FZ, x);
break;
}
}
while (FZ.data[FZ.top] != '#')
{
postexp[i++] = FZ.data[FZ.top];
x = FZ.data[FZ.top];
pop2(&FZ, x);
}
postexp[i] = '\0';
}
float evaluateExpression(char *postexp)
{
stack1 SZ;
initStack1(&SZ);
float a, b, d;
SZ.top = -1;
while (*postexp != '\0')
{
switch (*postexp)
{
case'+':
case'-':
case'*':
case'/':
a = SZ.data[SZ.top];
pop1(&SZ, a);
b = SZ.data[SZ.top];
pop1(&SZ, b);
push1(&SZ, operation(a, *postexp, b));
break;
default:
d = 0;
while (*postexp >= '0'&&*postexp <= '9')
{
d = 10 * d + *postexp - '0';
postexp++;
}
push1(&SZ, d);
SZ.data[SZ.top] = d;
break;
}
postexp++;
}
return(SZ.data[SZ.top]);
}
int err(char *exp)
{
int i = 0;
while (exp[i] != '\0')
{
if (
((exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/') && (exp[i + 1] == ')'))
|| ((exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/') && (exp[i - 1] == '('))
|| (exp[i] == ')'&&exp[i + 1] == '(')
|| (exp[i] == '('&&exp[i + 1] == ')')
|| ((exp[i] == ')') && exp[i + 1] >= '0'&&exp[i + 1] <= '9')
|| (exp[i] >= '0'&&exp[i] <= '9'&&exp[i + 1] == '(')
|| (exp[0] == '+' || exp[0] == '-' || exp[0] == '*' || exp[0] == '/' || exp[0] == ')')
|| ((exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/') && (exp[i + 1] == '+' || exp[i + 1] == '-' || exp[i + 1] == '*' || exp[i + 1] == '/'))
|| (exp[i] == '/'&&exp[i + 1] == '0')
)
return 1;
else
if (exp[i] == '\0')
return 0;
i++;
}
return 0;
}
int main()
{
char c;
char exp[maxsize];
char postexp[maxsize] = { 0 };
while (1)
{
sr :
int n;
scanf("%d",&n);
int i = 0;
for(int j = 0; j < n; j++)
{
string str2 = getExp();
for(i = 0;i < str2.length();i++)
exp[i] = str2[i];
exp[i] = '\0';
if (!err(exp))
{
transmitExpression(exp, postexp);
printf("%s\n", exp);
float numnum;
scanf("%g",&numnum);
if(numnum==evaluateExpression(postexp))
cout<<"正确"<<endl;
else
printf("=%g\n", evaluateExpression(postexp));
}
else if (err(exp))
{
printf("您输入的表达式有误!\n");
goto sr;//goto语句在循环体里进行跳转
}
}
}
system("pause");
return 0;
}