辅助判卷程序阶段性成果
目前已经大概完成程序的基础功能开发,实现功能为,读取txt文档中的题目,并显示在屏幕上,获取用户输入后,可根据电脑计算结果,判断对错,其中包括小数和分数两种形式。
自己定义了三个类,如下:
class unit { public: char op; double num; int kind; unit(){ kind=0; } void set(char c){ op=c; kind=1; } void set(double d){ num=d; kind=2; } };
后缀表达式的辅助存储结构,可同时存储数字与操作符。
class fenshu { public: int fz; int fm; fenshu(int a,int b){ fz=a;fm=b; yuefen(); } void yuefen(){ int t; int a=fz; int b=fm; if (a < b) { t = a; a = b; b = t; } while (t = a % b) { a = b; b = t; } if(b!=1){ fz/=b; fm/=b; } } void print(){ cout<<fz<<"/"<<fm; } fenshu operator +(fenshu &fs){ fenshu f(fz*fs.fm+fs.fz*fm,fm*fs.fm); f.yuefen(); return f; } fenshu operator -(fenshu &fs){ fenshu f(fz*fs.fm-fs.fz*fm,fm*fs.fm); f.yuefen(); return f; } fenshu operator *(fenshu &fs){ fenshu f(fz*fs.fz,fs.fm*fm); f.yuefen(); return f; } fenshu operator /(fenshu &fs){ fenshu f(fz*fs.fm,fm*fs.fz); f.yuefen(); return f; } void operator =(fenshu &fs){ fz=fs.fz; fm=fs.fm; } bool operator ==(fenshu &fs){ return fz==fs.fz&&fm==fs.fm; } };
分数类,定义了一系列关于分数的运算显示。
class Calculator { public: double result; //计算结果 fenshu fresult; //分数计算结果 bool error; //计算过程中是否有错误 string str; //存放中缀表达式 Calculator(string s):fresult(1,1){ //计算器初始化 clear(); str=s; } int run(){ //计算表达式的值,存入result if(zzh(str)==-1){ error=true; result=-1; return -1; } if(getResult()==-1){ error=true; result=-1; return -1; } int i; bool b=true; for(i=0;i<str.size();i++){ //没有小数点,就计算分数结果 if(str[i]=='.'){ b=false; break; } } if(b){ if(getFResult()==-1){ error=true; fenshu f(-1,-1); fresult=f; return -1; } } return 0; } void clear(){ //清空计算器 num=0; error=false; result=0; } void recalculator(string s){ //重启计算器对象 clear(); str=s; } void printfanswer(){ int i=0; for(;i<str.size();i++){ if(str[i]=='.'){ cout<<"答案为:"<<result<<endl; return; } } cout<<"答案为:";//<<result<<" 或 "; if(fresult.fm!=1) fresult.print(); else cout<<fresult.fz; cout<<endl; } private: unit u[80]; //存储后缀表达式 int num; //数量 int zzh(string s){ //中缀表达式转后缀表达式 char c; char temp1[80]; double temp; string stemp; stack<char> st; while(!s.empty()){ //如果字符串不为空则继续循环 c=s[0]; if(isoperator(c)){ //是操作符 s.erase(0,1); //从string中删除操作符 if(pushintostack(c,&st)==-1) //处理当前操作符 return -1; //出错处理 } else{ //是数字 stringstream sst(s); sst>>temp; sprintf(temp1,"%g",temp); stemp=temp1; s.erase(0,stemp.size()); //从string中删除数字 sst.clear(); u[num++].set(temp); //存储数字到栈中 } } if(pushintostack('#',&st)==-1) //字符串处理完毕,输出所有栈中剩余操作符 return -1; return 0; } bool isoperator(char c){ //判断是否是操作符 if(c=='+') return true; if(c=='-') return true; if(c=='*') return true; if(c=='/') return true; if(c=='(') return true; if(c==')') return true; return false; } int youxian(char c1,char c2){ //判断两操作符优先级 if(c2=='#') //结束符 return 0; if(c2=='(') return 1; if(c2==')') if(c1=='(') return 2; else return 0; if(c1=='(') if(c2=='+'||c2=='-'||c2=='*'||c2=='/') return 1; if(c1=='*'||c1=='/') return 0; if(c1=='+'||c1=='-') if(c2=='*'||c2=='/') return 1; else if(c2=='+'||c2=='-') return 0; return -1; } int pushintostack(char c,stack<char> *st){ //将操作符执行一系列入栈判断操作 char a; int y=0; while(!st->empty()){ a=st->top(); y=youxian(a,c); if(y==0){ //后来的操作符优先级小 st->pop(); u[num++].set(a); } else if(y==1){ //后来的操作符优先级大 //st->push(c); break; } else if(y==2){ //俩操作符是'('和')' st->pop(); return 0; } else return -1; } st->push(c); return 0; } void test(){ int i; cout<<num<<endl; for(i=0;i<num;i++){ if(u[i].kind==1) cout<<u[i].op<<" "; else if(u[i].kind==2) cout<<u[i].num<<" "; } } int getResult(){ int i; char op; double num1,num2; stack<double> st; for(i=0;i<num;i++){ //处理后缀表达式 if(u[i].kind==2){ //如果是数字则入栈 st.push(u[i].num); } else if(u[i].kind==1){ //如果是操作符,则出栈两个数字 op=u[i].op; if(st.empty()) return -1; num2=st.top(); st.pop(); if(st.empty()) return -1; num1=st.top(); st.pop(); switch(op){ case '+': st.push(num1+num2); break; case '-': st.push(num1-num2); break; case '*': st.push(num1*num2); break; case '/': if(num2==0) return -1; st.push(num1/num2); break; } } else return -1; } result=st.top(); return 0; } int getFResult(){ int i; char op; fenshu f1(1,1),f2(1,1); stack<fenshu> st; for(i=0;i<num;i++){ if(u[i].kind==2){ //如果是数字则入栈 st.push(fenshu(u[i].num,1)); } else if(u[i].kind==1){ //如果是操作符,则出栈两个数字 op=u[i].op; if(st.empty()) return -1; f2=st.top(); st.pop(); if(st.empty()) return -1; f1=st.top(); st.pop(); switch(op){ case '+': st.push(f1+f2); break; case '-': st.push(f1-f2); break; case '*': st.push(f1*f2); break; case '/': if(f2.fz==0) return -1; st.push(f1/f2); break; } } else return -1; } fresult=st.top(); return 0; } };
计算器类,核心类,可对符合标准的字符串进行识别与运算。
int main(int argc, char** argv) { ifstream in("shit.txt"); Calculator cal(""); string s; string answer; int i=0,j; bool b; if(!in){ cout<<"打开文件出错"<<endl; return -1; } else{ while(in>>s){ b=true; cal.recalculator(s); cal.run(); cout<<"第"<<++i<<"题:"<<endl; cout<<s<<"="; cin>>answer; for(j=0;j<answer.size();j++){ if(answer[j]=='/'){ b=false; break; } } if(b){ //用户输入为小数形式 if(atof(answer.c_str())==cal.result) b=true; else b=false; } else{ //用户输入为分数形式 stringstream sst(answer); int n1,n2; char c; sst>>n1>>c>>n2; if(c!='/'){ cout<<"输入非法"<<endl; } else{ fenshu f(n1,n2); if(f==cal.fresult) b=true; else b=false; } } if(b){ cout<<"答案正确"<<endl; } else{ cout<<"答案错误"<<endl; cal.printfanswer(); } cout<<endl; } } in.close(); return 0; }
main函数,包括了从文件中读取算式,并调用calculator中的函数等一系列操作,程序的主体。
接下来的任务,尝试编写随机算式的生成。