用C语言实现的带括号四则运算计算器,原理简单,即模拟笔算,将每个运算符标记等级,计算时按照等级由高到低进行计算。加减运算为0级,乘除运算为1级,每进入一层括号等级加2。使用两个链表分别储存运算符与数字。主程序调用之前实现的两个模块,一个是链表,另一个是分数计算。链表代码在下一篇文章,只贴出主程序和分数计算部分。
主程序,检查算式是否合法的函数未实现
1 #include "list.h"
2 #include "sz.h"
3
4 /*内部类型、常量、函数*/
5
6 #define LEVEL_NUM 20 //支持的运算级数
7
8 typedef struct
9 {
10 List *oper; //存运算符的链表,data段类型为Op *
11 List *num; //存数字的链表,data段类型为Fract *
12 int oper_num[LEVEL_NUM]; //存每一级的运算符个数
13 }Pack;
14
15 typedef struct
16 {
17 char oper;
18 int level;
19 }Op; //运算符及对应的级别,加减0级,乘除1级,每进入一层括号运算符对应的级别加2
20
21
22 static void Convert(char equation[],Pack *pack);
23 static int str2int(char str[],int start,int end);
24 static int GetSE(char str[],int s,int flag);
25 static void Compute(Pack *pack,Fract *ans);
26
27
28 int main(void)
29 {
30 char equation[100];
31 Fract ans;
32 while(1)
33 {
34 scanf("%s",equation);
35 calc(equation,&ans);
36 printf("%d/%d\n",ans.numer,ans.deno);
37 }
38 return 0;
39 }
40
41 void calc(char equation[],Fract *ans)
42 {
43 Pack pack;
44
45 //检查及完善equation,该函数未实现!!
46
47 //转换并存入链表
48 Convert(equation,&pack);
49
50 //使用链表计算,并释放
51 Compute(&pack,ans);
52
53 }
54
55 //特别说明
56 //对于"(-数字"这种形式,会导致str2int的参数start>end,正好会转化成"(0-数字"的形式
57 //因此没有用库函数
58 void Convert(char equation[],Pack *pack)
59 {
60 int i,base,start;
61
62 Op *op;
63 Fract *num;
64
65 //初始化
66 pack->num=CreateList();
67 pack->oper=CreateList();
68 for(i=0;i
69 pack->oper_num[i]=0;
70
71 start=GetSE(equation,0,1);
72 base=0; //存级别的基,每进入一层括号基加2
73 for(i=0;equation[i];i++)
74 switch(equation[i])
75 {
76 case '+':case '-':case '*':case '/':
77 //添加运算符
78 op=(Op *)malloc(sizeof(Op));
79 op->oper=equation[i];
80 op->level=base+
81 ( (equation[i]=='+'||equation[i]=='-')?0:1);
82 AddNode(pack->oper,op,pack->oper->n); //插入到链表尾
83 pack->oper_num[op->level]++;
84
85 //添加数字
86 num=(Fract *)malloc(sizeof(Fract));
87 num->numer=str2int(equation,start,GetSE(equation,i-1,-1));
88 num->deno=1;
89 AddNode(pack->num,num,pack->num->n);
90 start=GetSE(equation,i+1,1); //为下一个数字准备
91 break;
92 case '(':
93 base+=2;
94 break;
95 case ')':
96 base-=2;
97 break;
98 default: //数字字符
99 break;
100 }
101
102 //运算符和数字成对出现,存入最后多出的数字
103 num=(Fract *)malloc(sizeof(Fract));
104 num->numer=str2int(equation,start,GetSE(equation,i-1,-1));
105 num->deno=1;
106 AddNode(pack->num,num,pack->num->n);
107 }
108
109
110 //将由start和end脚标确定的字符串转换为整数
111 int str2int(char str[],int start,int end)
112 {
113 int i,s=0;
114 for(i&#61;start;i<&#61;end;i&#43;&#43;)
115 s&#61;s*10&#43;str[i]-&#39;0&#39;;
116 return s;
117 }
118
119
120 //从s开始向前或向后找第一个数字字符的角标
121 //flag为1向后&#xff0c;-1向前
122 int GetSE(char str[],int s,int flag)
123 {
124 int i;
125 for(i&#61;s;i>&#61;0 && str[i] && !isdigit(str[i]);i&#43;&#61;flag)
126 ;
127 return i;
128 }
129
130 void Compute(Pack *pack,Fract *ans)
131 {
132 //前一运算符&#xff0c;运算符
133 //第一个数字,第二个数字
134 Node *pop,*op,*num,*nnum;
135 int i;
136
137 //找到最高不为0的一级
138 for(i&#61;LEVEL_NUM-1;i>&#61;0 && !pack->oper_num[i];i--)
139 ;
140
141 for(;i>&#61;0;i--) //由高到低级依次计算
142 for(pop&#61;pack->oper->head,op&#61;pack->oper->head->next,num&#61;pack->num->head->next;
143 pack->oper_num[i] ; )
144 if( ((Op*)(op->data))->level&#61;&#61;i ) //找到级别为i的运算符
145 {
146 pack->oper_num[i]--;
147 switch( ((Op*)(op->data))->oper)
148 {
149 //计算&#xff0c;结果存入第一个数中
150 case &#39;&#43;&#39;:Plus(num->data,num->next->data);
151 break;
152 case &#39;-&#39;:Minus(num->data,num->next->data);
153 break;
154 case &#39;*&#39;:Multiply(num->data,num->next->data);
155 break;
156 case &#39;/&#39;:Divide(num->data,num->next->data);
157 break;
158 default:
159 printf("\nCompute函数出现不可能运算符 %c\n",((Op*)(op->data))->oper);
160 exit(0);
161 break;
162 }
163
164 //删除计算完成的运算符、数字
165 pack->num->n--;
166 pack->oper->n--;
167 pop->next&#61;op->next;
168 nnum&#61;num->next;
169 num->next&#61;nnum->next;
170 free(nnum->data);free(op->data);
171 free(nnum);free(op);
172
173 op&#61;pop->next; //恢复op的指向
174 }
175 else //没找到时继续遍历链表
176 pop&#61;op,op&#61;op->next,num&#61;num->next;
177
178 //计算完成后&#xff0c;仅剩一个的数字为结果&#xff0c;运算符链表没内容&#xff0c;储存运算符级别的个数的数组各元素为0
179 if(pack->num->n!&#61;1 || pack->oper->n || pack->oper_num[0])
180 {
181 printf("Compute函数内变量异常&#xff0c;数字个数 %d&#xff0c;运算符个数 %d&#xff0c;0级个数 %d",
182 pack->num->n,pack->oper->n,pack->oper_num[0]);
183 exit(0);
184 }
185 (*ans)&#61;*(Fract *)pack->num->head->next->data;
186 DestroyList(pack->num);
187 DestroyList(pack->oper);
188 }
1 #ifndef SZ_H
2 #define SZ_H
3
4 //只有calc函数对外&#xff0c;可以去掉主函数来当做一个计算模块使用
5 //只要在项目中添加sz、list、fract
6
7 #include
8 #include "fract.h"
9
10 void calc(char equation[],Fract *ans);
11
12 #endif
分数计算部分
1 #include "fract.h"
2
3 static int commom_divisor(int a,int b); //最大公约数
4 static int common_multiple(int a,int b);//最小公倍数
5 static void reduce(int *num1,int *num2); //约分
6
7
8 void Plus(Fract *num1,Fract *num2)
9 {
10 int deno;//公分母
11
12 if(num1->numer&#61;&#61;0) //排除0值计算
13 {
14 *num1&#61;*num2;
15 return;
16 }
17 else if(num2->numer&#61;&#61;0) return;
18
19 deno&#61;common_multiple(num1->deno,num2->deno);
20 num1->numer&#61;deno/num1->deno*num1->numer&#43;deno/num2->deno*num2->numer;
21 num1->deno&#61;deno;
22
23 }
24
25 void Minus(Fract *num1,Fract *num2)
26 {
27 num2->numer&#61;-num2->numer;
28 Plus(num1,num2);
29 }
30
31 void Multiply(Fract *num1,Fract *num2)
32 {
33 if(num1->numer&#61;&#61;0)return;
34 else if(num2->numer&#61;&#61;0)
35 {
36 num1->numer&#61;0;
37 return;
38 }
39
40 reduce(&num1->deno,&num2->numer);
41 reduce(&num1->numer,&num2->deno);
42
43 num1->numer*&#61;num2->numer;
44 num1->deno*&#61;num2->deno;
45
46 }
47
48 void Divide(Fract *num1,Fract *num2)
49 {
50 int temp;
51 if(num2->numer&#61;&#61;0)
52 {
53 printf("除数不能为0\n");
54 exit(0);
55 }
56 temp&#61;num2->numer;
57 num2->numer&#61;num2->deno;
58 num2->deno&#61;temp;
59 Multiply(num1,num2);
60 }
61
62
63 static void reduce(int *num1,int *num2) //约分并保持原来的正负号
64 {
65 int temp,i;
66
67 /*i为0表示都为正&#xff0c;i为1表示num1为正&#xff0c;2表示num2为正&#xff0c;3表示都为负*/
68 if(*num1<0)
69 {
70 *num1&#61;-*num1;
71 if(*num2<0)
72 {
73 *num2&#61;-*num2;
74 i&#61;3;
75 }
76 else i&#61;2;
77 }
78 else
79 if(*num2<0)
80 {
81 *num2&#61;-*num2;
82 i&#61;1;
83 }
84 else i&#61;0;
85
86 temp&#61;commom_divisor(*num1,*num2);
87 *num1/&#61;temp;
88 *num2/&#61;temp;
89
90 switch(i)
91 {
92 case 0:break;
93 case 1:*num2&#61;-*num2;break;
94 case 2:*num1&#61;-*num1;break;
95 case 3:*num1&#61;-*num1;*num2&#61;-*num2;break;
96 }
97 }
98
99
100 static int commom_divisor(int a,int b)
101 {
102 int temp,r;
103
104 if(a<b)
105 {
106 temp&#61;a;
107 a&#61;b;
108 b&#61;temp;
109 }
110
111 while((r&#61;a%b))
112 {
113 a&#61;b;
114 b&#61;r;
115 }
116
117 return b;
118 }
119
120 static int common_multiple(int a,int b)
121 {
122 return a*b/commom_divisor(a,b);
123 }
1 #ifndef FRACT_H
2 #define FRACT_H
3
4 #include
5 #include
6
7 //如果有负号则在分子上
8 typedef struct
9 {
10 int numer; //分子
11 int deno; //分母
12 }Fract;
13
14 //分数的四则运算&#xff0c;结果存在num1中
15 void Plus(Fract *num1,Fract *num2);
16 void Minus(Fract *num1,Fract *num2);
17 void Multiply(Fract *num1,Fract *num2);
18 void Divide(Fract *num1,Fract *num2);
19
20 #endif
控制台程序源代码 sz.7z
借用如鹏的对话框模版&#xff0c;及上面的计算器部分&#xff0c;实现的图形计算器
代码及程序 calc.7z