1 #include<stdio.h>
2 #include<math.h>
3 #include<stdlib.h>
4
5 typedef struct stack1 {
6 char data[20];
7 int top;
8 } StackChars;
9
10 typedef struct stack2 {
11 double data[20];
12 int top;
13 } StackDatas;
14
15 double calculator(char str[100]);
16 char getUnary(char str[20], int * key);
17 int getLevel(char a);
18 void InitStackdata(StackDatas* sdt);
19 void InitStackchar(StackChars* stc);
20 void Pushd(StackDatas* stc, double x);
21 void Pushc(StackChars* stc, char x);
22 void Popd(StackDatas* sdt, double * y);
23 void Popc(StackChars* sdt, char * y);
24 void cal(StackDatas* sdt, char a);
25 double toData(char str[20], int* key);
26 int stackIn(char a, char top);
27
28 double calculator(char str[100]) {
29 StackChars stackCh;
30 StackDatas stackDa;
31 InitStackdata(&stackDa);
32 InitStackchar(&stackCh);
33 Pushc(&stackCh, '=');
34 int i = 0, sign = 1;/*sign标记是否是表达式最开始*/
35
36 while (str[i] != '='&&str[i]) {
37 while (str[i] == ' ')i++;
38 if (sign && (str[i] == '+' || str[i] == '-'))
39 {
40 Pushd(&stackDa, 0);/*处理表达式或(后直接带的第一个正负号*/
41 }
42 if (str[i] >= '0'&&str[i] <= '9' || str[i] == '.')
43 {
44 Pushd(&stackDa, toData(str, &i));/*把字符转化操作数,并放入对应栈中*/
45 sign = 0;
46 while (str[i] == ' ')i++;
47 }
48 else if (str[i] >= 'a'&&str[i] <= 'z')
49 {
50 Pushc(&stackCh, getUnary(str, &i));/*单目运算符(不含括号)可直接放入栈中*/
51 while (str[i] == ' ')i++;
52 }
53 else if (str[i] == ')') {
54 char x = '!';
55 while (stackCh.data[stackCh.top] != '(') {/*用括号中的操作符运算*/
56 Popc(&stackCh, &x);
57 cal(&stackDa, x);
58 }
59 Popc(&stackCh, &x);/*删掉(不运算*/
60 i++;
61 while (str[i] == ' ')i++;
62 }
63 else {
64 if (str[i] == '(')
65 sign = 1;
66 if (stackIn(str[i], stackCh.data[stackCh.top]))
67 Pushc(&stackCh, str[i]);
68 else {
69 int stop = 0, cur = stackCh.top;
70 while (!stop)
71 {
72 stackCh.top--;
73 cal(&stackDa, stackCh.data[cur]);
74 cur--;
75 stop = stackIn(str[i], stackCh.data[cur]);
76 }
77 Pushc(&stackCh, str[i]);
78 }
79 i++;
80 }
81 }
82 char x;
83 double result;
84 while (stackCh.data[stackCh.top] != '=') {
85
86 Popc(&stackCh, &x);
87 cal(&stackDa, x);
88 }
89 Popc(&stackCh, &x);
90 Popd(&stackDa, &result);
91 return result;
92 }
93
94 char getUnary(char str[20], int * key) {
95 char unary[6];/*记录单目运算符*/
96 int j = 0;
97 while (str[*key] >= 'a'&&str[*key] <= 'z')
98 {
99 unary[j++] = str[*key];
100 (*key)++;
101 }
102 unary[j] = '\0';
103 if (strcmp(unary, "sin") == 0)return 's';
104 else if (strcmp(unary, "cos") == 0) return 'c';
105 else if (strcmp(unary, "log") == 0) return 'o';
106 else { if (strcmp(unary, "ln") == 0) return 'n'; }
107
108 }
109
110 int getLevel(char a) {/*得到操作符优先级,除了操作符外其他字符返回-1,对于数字和'.'的判断不用此函数*/
111 switch (a) {
112 case'=':return 0;
113 case'+':return 1;
114 case'-':return 1;
115 case'*':return 2;
116 case'/':return 2;
117 case'^':return 2;
118 case's':return 3;/*sin*/
119 case 'c':return 3;/*cos*/
120 case'o':return 3;/*log*/
121 case'n':return 3;/*ln*/
122 case'(':return 4;/*'('进入栈前为最大4,进入栈后为最小0*/
123 default:return -1;
124 }
125 }
126
127 void InitStackdata(StackDatas* sdt) {
128 (*sdt).top = -1;
129 }
130
131 void InitStackchar(StackChars* stc) {
132 (*stc).top = -1;
133 }
134
135 void Pushd(StackDatas* stc, double x) {
136 (*stc).top++;
137 (*stc).data[(*stc).top] = x;
138 }
139
140 void Pushc(StackChars* stc, char x) {
141 (*stc).top++;
142 (*stc).data[(*stc).top] = x;
143 }
144
145 void Popd(StackDatas* sdt, double * y) {
146 *y = (*sdt).data[(*sdt).top];
147 (*sdt).top--;
148 }
149
150 void Popc(StackChars* sdt, char * y) {
151 *y = (*sdt).data[(*sdt).top];
152 (*sdt).top--;
153 }
154
155
156 void cal(StackDatas* sdt, char a) {
157 double top1 = (*sdt).data[(*sdt).top];
158 double top2 = (*sdt).data[(*sdt).top - 1];
159 double result = 0.0;
160 switch (a) {
161 case'+':result = top1 + top2;
162 (*sdt).top--;
163 break;
164 case'-':result = top2 - top1;
165 (*sdt).top--;
166 break;
167 case'*':result = top2 * top1;
168 (*sdt).top--;
169 break;
170 case'/':result = top2 / top1;
171 (*sdt).top--;
172 break;
173 case'^':result = pow(top2, top1);
174 (*sdt).top--;
175 break;
176 case's':/*sin*/
177 result = sin(top1);
178 break;
179 case 'c':/*cos*/
180 result = cos(top1);
181 break;
182 case'o':/*log*/
183 result = log10(top1);
184 break;
185 case'n':/*ln*/
186 result = log(top1);
187 break;
188 }
189 (*sdt).data[(*sdt).top] = result;
190 }
191
192 double toData(char str[20], int* key) {
193 char rel[20] = { '\0' };
194 int i = 0;
195 while (str[*key] >= '0'&&str[*key] <= '9' || str[*key] == '.') {
196 rel[i] = str[*key];
197 i++;
198 (*key)++;
199 }
200 rel[i] = '\0';
201 return atof(rel);
202 }
203
204 int stackIn(char a, char top) {/*返回1 a可直接进栈*/
205 int x = getLevel(a);
206 int y = getLevel(top);
207 if (top == '(')/*栈内(为0*/
208 y = 0;
209 if (x <= y)
210 return 0;/*a不能直接进栈*/
211 else
212 return 1;
213 }
214
215
216
217 int main() {
218 char str[100];
219 while (1) {//这个我直接按叉号结束程序,有更好方法可以改
220 gets(str);
221 printf("%.4f \n", calculator(str));//按保留小数点后4位,可修改
222 }
223
224 system("pause");
225 }