码迷,mamicode.com
首页 > 其他好文 > 详细

采用进出栈方式设计简单计算器

时间:2020-04-22 19:42:01      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:sys   main   nbsp   log   pause   表达   优先级   ret   数字   

  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     cases:return 3;/*sin*/
119     case c:return 3;/*cos*/
120     caseo:return 3;/*log*/
121     casen: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     cases:/*sin*/
177         result = sin(top1);
178         break;
179     case c:/*cos*/
180         result = cos(top1);
181         break;
182     caseo:/*log*/
183         result = log10(top1);
184         break;
185     casen:/*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 }

 

采用进出栈方式设计简单计算器

标签:sys   main   nbsp   log   pause   表达   优先级   ret   数字   

原文地址:https://www.cnblogs.com/logcabin/p/12754878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!