标签:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<math.h>
using namespace std;
#define EPS 1e-5
char s[50];
int val[300];
void gao(char str[])//把中缀表达式转换成后缀
{
int cnt = 0;
stack<int> st;//符号栈
int len = strlen(str);
for(int i = 0;i<len;i++)
{
if(str[i]==‘(‘) st.push(str[i]);//对左括号的处理
else if(str[i]==‘)‘)//对右括号的处理
{
while(!st.empty())
{
int u = st.top();
st.pop();
if(u==‘(‘) break;
s[cnt++] = u;
}
}
else if(str[i]==‘+‘||str[i]==‘-‘||str[i]==‘*‘||str[i]==‘/‘)//对运算符的处理
{
while(!st.empty())
{
int u = st.top();
if(u==‘(‘||val[str[i]]>val[u]) break;
st.pop();
s[cnt++] = u;
}
st.push(str[i]);
}
else//数字直接加入字符串
{
s[cnt++] = str[i];
}
}
//把还在栈中的符号出栈
while(!st.empty())
{
int u = st.top();
st.pop();
s[cnt++] = u;
}
s[cnt] = 0;
}
int gcd(int a,int b)//求最大公约数
{
return b==0? a:gcd(b,a%b);
}
int lcm(int a,int b)//求最小公倍数
{
return a*b/gcd(a,b);
}
pair<int,int> cal(char str[])//计算值,已分数表示
{
int a,b;
stack<pair<int,int> > st;//存放值的栈,用分数表示
int len = strlen(str);
for(int i = 0;i<len;i++)
{
if(str[i]>=‘0‘&&str[i]<=‘9‘)
{
st.push(make_pair(str[i]-‘0‘,1));//现转化为分数
}
else
{
pair<int,int> pa1 = st.top();
st.pop();
pair<int,int> pa2 = st.top();
st.pop();
int LCM = lcm(pa1.second,pa2.second);
if(str[i]==‘+‘)//对加法的处理
{
//if(pa1.second==0||pa2.second==0) return make_pair(0,0);
int a = pa1.first*(LCM/pa1.second);
int b = pa2.first*(LCM/pa2.second);
pa1.first = a+b;
pa1.second = LCM;
st.push(pa1);//入栈
}
else if(str[i]==‘-‘)//对减法的处理
{
int a = pa1.first*(LCM/pa1.second);
int b = pa2.first*(LCM/pa2.second);
pa1.first = b-a;
pa1.second = LCM;
st.push(pa1);
}
else if(str[i]==‘*‘)//对乘法的处理
{
pa1.first = pa1.first*pa2.first;
pa1.second = pa1.second*pa2.second;
st.push(pa1);
}
else//对除法的处理
{
if(pa1.first==0) return make_pair(0,0);//改进了对除0的处理
int a = pa2.first*pa1.second;
int b = pa2.second*pa1.first;
pa1.first = a,pa1.second = b;
st.push(pa1);
}
}
}
pair<int,int> pa = st.top();
st.pop();
int GCD = gcd(pa.first,pa.second);
pa.first/=GCD,pa.second/=GCD;//化成最简形式
return pa;
}
int check(char str[])//判断str字符串是否合法
{
int a = 0;
int len = strlen(str);
for(int i = 0;i<len;i++)
{
if(str[i]==‘(‘) a++;
else if(str[i]==‘)‘)a--;
if(a<0) return 0;
if(str[i]==‘)‘&&i>=2&&str[i-2]==‘(‘) return 0;
}
if(str[0]==‘(‘&&str[strlen(str)-1]==‘)‘) return 0;
return 1;
}
int ok(int a,int b,char str[]) //判断在str的ab位置放括号的合法性
{
if(str[a]<‘0‘||str[b]<‘0‘||str[a]>‘9‘||str[b]>‘9‘) return 0;
if(b<=a) return 0;
if(a==0&&b==strlen(str)-1) return 0;
if(a!=0&&str[a-1]==‘(‘&&str[b+1]==‘)‘) return 0;
return 1;
}
void pro(char str[])//随机产生一个四则运算
{
int sum = rand()%3; //随机括号的个数
for(int i = 0;i<=6;i++)
{
if(i%2==0)
{
str[i] = rand()%9+1+‘0‘;
}
else
{
int temp = rand()%4;
if(temp==0) str[i] = ‘+‘;
if(temp==1) str[i] = ‘-‘;
if(temp==2) str[i] = ‘*‘;
if(temp==3) str[i] = ‘/‘;
}
}
str[7] = 0;
for(int i= 1;i<=sum;i++)//循环增加括号
{
int a = rand()%(7+2*i-2);
int b = rand()%(7+2*i-2);
while(!ok(a,b,str))
{
a = rand()%(7+2*i-2);
b = rand()%(7+2*i-2);
}
char ss[100];
int cnt = 0;
for(int j = 0;j<7+2*i-2;j++)
{
if(j==a)
{
ss[cnt++] = ‘(‘;
ss[cnt++] = str[j];
}
else if(j==b)
{
ss[cnt++] = str[j];
ss[cnt++] = ‘)‘;
}
else ss[cnt++] = str[j];
}
ss[cnt] = 0;
int flag = check(ss);
if(!flag) i--;
else
{
strcpy(str,ss);
}
}
// printf("%s\n",str);
// gao(str);
// pair<int,int> pa = cal(s);
// printf("%d %d\n",pa.first,pa.second);
}
int is_ok(int a, int b)//判断a/b是否是无限循环小数
{
if(b==0) return 0;
if(a==0) return 1;
map<int,int> ma;
while(1)
{
while(a<b) a*=10;
if(a%b==0) return 1;
if(ma[a%b]) return 0;
ma[a%b] = 1;
a = a%b;
}
}
void pri(int a,int b)//打印a/b的值
{
if(a==0)//如果为0直接输出防止后面运算出bug
{
printf("0");
return;
}
printf("%d.",a/b);
a = a%b;
//a*=10;
while(1)
{
int flag = 0;
while(a<b)
{
a*=10;
if(flag)
printf("0");
flag++;
}
printf("%d",a/b);
a = a%b;
if(a==0) break;
}
}
int is_num(char str[])//判断str是否为正整数
{
int sum = 0;
int len = strlen(str);
for(int i = 0;i<len;i++)
{
if(str[i]>=‘0‘&&str[i]<=‘9‘) sum = sum*10+str[i]-‘0‘;
else return -1;
}
if(sum==0) return -1;
else return sum;
}
int main(int argc,char *argv[10])
{
srand(time(0));//初始化随机种子
val[‘+‘] = val[‘-‘] = 1;
val[‘*‘] = val[‘/‘] = 2;//运算符的优先级
if(argc==1)//功能1,2
{
int sum = 0;
char str[50];
for(int i = 1;i<=20;i++)
{
pro(str);
gao(str);
pair<int,int> pa = cal(s);
// printf("%s\n",str);
if(pa.second==0)//说明有除0现象
{
i--;
continue;
}
//printf("%d %d\n",abs(pa.first),abs(pa.second));
if(is_ok(abs(pa.first),abs(pa.second)))//不能整除继续寻找
{
printf("%s\n?",str);
}
else
{
i--;
continue;
}
//printf("%d %d\n",abs(pa.first),abs(pa.second));
//printf("%s\n",s);
double res;
scanf("%lf",&res);
// printf("%lf\n",res-1.0*pa.first/pa.second);
if(fabs(res-1.0*pa.first/pa.second)<EPS)//eps为误差值,用于double比较
{
sum++;
printf("答对了,你真是个天才!\n");
}
else
{
if(abs(pa.first)%abs(pa.second)==0)//整除直接输出
{
printf("在想想吧,答案似乎是%d喔!\n",pa.first/pa.second);
}
else
{
int flag = 0;
if(pa.first<0) flag++;
if(pa.second<0) flag++;
printf("在想想吧,答案似乎是");
if(flag%2==1) printf("-");
pri(abs(pa.first),abs(pa.second));
printf("喔!\n");
}
}
}
printf("你一共对了%d道题,共20道题.\n",sum);
}
if(argc==3)//功能3,4
{
int flag = is_num(argv[2]);
if(flag==-1) {printf("题目数量必须是 正整数。\n");return 0;}
for(int i = 1;i<=flag;i++)
{
char str[100];
// printf("111111\n");
pro(str);
gao(str);
printf("%-50s%",str);
// printf("%s\n",str);
pair<int,int> pa = cal(s);
// printf("%d 2222222\n",i);
if(pa.second==0) {
i--;continue;
}
if(pa.first%pa.second==0) printf("%d\n",pa.first/pa.second);
else
{
int flag = 0;
if(pa.first<0) flag++;
if(pa.second<0) flag++;
if(flag%2) printf("-");
pa.first = abs(pa.first);//正负提取,取绝对值
pa.second = abs(pa.second);
if(pa.first/pa.second) printf("%d ",pa.first/pa.second);
pa.first-=pa.first/pa.second*pa.second;
printf("%d/%d\n",pa.first,pa.second);//输出答案
}
// printf("11111\n");
}
}
return 0;
}



结对作业:李峤 杜月
标签:
原文地址:http://www.cnblogs.com/liqiao085/p/5873614.html