本文实例为大家分享了C语言实现数学表达式运算的具体代码,供大家参考,具体内容如下
1、开发思路: (假设有表达式 2 * 3 * ( 1 + 2) )
数字要一个一个取出放在内存中,根据相邻前后2个计算符号,判断是否要取出数字进行计算,2个数字的计算值重新放在内存中且顺序放置。考虑使用栈这种数据结构去保存数字和符号,用2个栈,1个栈保存数字,一个栈保存运算符号。
2、因要使用栈这种数据结构,本代码使用纯C语言开发,故先编写栈的代码,参考:
c语言实现通用数据结构(三):通用椎栈
3、重要处理逻辑
(1)如何判断前后2个运算符的优先级关系
(2)如何字符转换为数字
因键盘输入的内容为字符类型,需要判断输入的字符类型且进行必要转换
ASCII码表,表头依次为:二进制 十进制 十六进制 字符
(3)如何判断表达式处理完毕
默认先预置一个符号#,输入内容2 * 3 * ( 1 + 2)# ,当符号栈内为#,且当前处理的字符为#。则表达式处理完毕。
4、代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include <stdlib.h> #include <stdio.h> #include "myStack.h" // 判断是否操作符 int ifOp(char c) { switch (c) { case '+': return 1; case '-': return 1; case '*': return 1; case '/': return 1; case '(': return 1; case ')': return 1; case '#': return 1; default: break; } return 0; } int findOffset(char * str,char c,int len) { for (int i = 0; i < len;i++) { if (str[i] == c) { return i; } } return -1; } //判断任意相继出现的2个运算符的优先级 char yxji(char op1,char op2) { char ops[] = "+-*/()#"; char oplist[7][7] = { ">><<<>>", ">><<<>>", ">>>><>>", ">>>><>>" , "<<<<<=&", ">>>>&>>", "<<<<<&="}; int len = sizeof(ops) / sizeof(char); return oplist[findOffset(ops,op1, len)][findOffset(ops, op2, len)]; } //基础运算 a-第1个数 b-第2个数 void baseOp(char op,int a,int b,int * value) { printf("baseOp %d %c %d",a,op,b); //int value = 0; //int* p = &value; switch (op) { case '+': *value = a + b; break; case '-': *value = a-b; break; case '*': *value = a*b; break; case '/': *value = a/b; break; default: printf("运算符不合法"); exit(1); } } //转换字符为数字 void transValue(char c,int * v) { if (c > 47 && c < 58) { *v = (c - 48); } } void printstack(MyStack * stack1,MyStack * stack2) { int len1 = myListGetSize(stack1); int len2 = myListGetSize(stack2); printf("stack1值:"); for (int i = 0; i < len1;i++) { char* m = (char*)myListGetDataAt(stack1,i ); printf("%c ", *m); } printf("nstack2值:"); for (int i = 0; i < len2; i++) { int* m = (int*)myListGetDataAt(stack2, i); printf("%d(%p) ", *m,m); } printf("n"); } // 计算,该方法只能对数字 0-9 运算(可掌握栈、指针的使用) // 2*3*(1+2)# void calculate(char bds[]) { int i = 0; char flag = '#'; MyStack* stack1 = createMyStack();//stack1中放运算符 myStackPush(stack1, &flag); MyStack* stack2 = createMyStack();//stack2中放数字 //char c = bds[i]; // 等价于*(bds+i) while (bds[i] != '#' || *(char*)myStackGetTop(stack1)!='#') { printstack(stack1,stack2); if (!ifOp(bds[i])) { /* * 这种写法不行! int vv = 0; transValue(bds[i], &vv) */ int* vu = (int*)malloc(sizeof(int)); transValue(bds[i], vu); printf("is number:%dn", *vu);//打印出数字 myStackPush(stack2, vu); i++; } else { printf("is fuhao:%cn", bds[i]); char * op1 = (char*)myStackGetTop(stack1); printf("top1 op:%cn",*op1); if (*op1 == '#') { myStackPush(stack1, &bds[i]); i++; continue; } char res = yxji(*op1, bds[i]); printf("yxji:%cn",res); switch (res) { case '>':{ char* curop = (char*)myStackPop(stack1);//取出当前运算符 printf("top2 op:%cn", *op1); int* b = (int*)myStackPop(stack2);//第2个运算数 int* a = (int*)myStackPop(stack2);//第1个运算数 /* * 这种写法不行! int value = 0; baseOp(*curop,transValue(*a), transValue(*b),&value); */ int* value = (int*)malloc(sizeof(int)); baseOp(*curop, *a, *b, value); printf("=%dn", *value); myStackPush(stack2, value); break; } case '<': myStackPush(stack1, &bds[i]); i++; break; case '=': { printf("()=="); myStackPop(stack1);//取出右括号 ( i++; break; } default: printf("表达式错误!"); exit(1); } } } int * valueRes = (int*)myStackPop(stack2); printf("计算结果值为:%dn",*valueRes); freeMyList(stack1); freeMyList(stack2); } int main() { printf("输入表达式:n"); char bds[50]; scanf("%s",bds);// 数组变量名,传入的相当于是数组第一个元素的地址。方法形参是个指针变量,指针变量才能存放地址 calculate(bds); return 0; }
5、代码开发过程总结 (踩坑填坑真实记录)
将符号转为数字并把数字放入栈中,若写为如下形式不行
int vv = 0;
transValue('1‘, &vv);
myStackPush(stack2, vv);
因为临时变量地址始终不变,第2个值赋值后,等于是把已放入栈内的第一个值修改了(程序中通过打印出指针变量值,即变量的地址,发现地址确实没变)
应该用如下方式:
int* vv= (int*)malloc(sizeof(int));
transValue('1‘, vv);
myStackPush(stack2, vv);
掌握指针用法很重要!此处记录如下:
6. 代码测试结果(开发环境:visual studio 2019)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是疯狂山水最近收集整理的关于C语言实现数学表达式运算的全部内容,更多相关C语言实现数学表达式运算内容请搜索靠谱客的其他文章。
发表评论 取消回复