计算器是栈的教科书级应用。这个项目从 V1.0 迭代到 V1.2,最终版约 1100 行,从”能算 1+2*3“一路做到:+ - * / ^ 五则运算、{} [] () 三种括号混用、小数,甚至 sin(1+sin(1+sin(1))) 这样的嵌套函数调用——全部纯 C 手写。

核心算法:两个栈消灭优先级

人脑算 3 + 4 * 2 时知道先乘除后加减,机器靠两个栈来消灭优先级问题:

  • 数字栈:存放操作数
  • 符号栈:存放运算符,利用优先级决定何时计算

整个算法分两步:

  1. 中缀转后缀:将 3 + 4 * 2 转为 3 4 2 * +(后缀表达式/逆波兰式),后缀表达式不需要任何优先级判断
  2. 后缀求值:逐个读 token,数字入栈,运算符弹出两个数计算后与压回,最后栈里剩下的就是答案

先造工具:My_Stack

写计算器之前先造轮子。栈用 calloc 分配、realloc 扩容,base/top/max 三个指针管理一段连续内存:

1
2
3
4
5
6
7
struct my_Stack
{
ll stack_size;
Elemtype* base;
Elemtype* top;
Elemtype* max;
};

Elemtype 用宏定义成 intlllong int 的别名——这套栈天生是为”下标入栈”准备的(后面会看到为什么)。压栈前检查满栈,满了就扩容一倍;弹栈前检查空栈:

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
bool Push(struct my_Stack* Stack, Elemtype ele)
{
if(Stack_full(Stack) == true)
{
if(Stack_new(Stack,Stack->stack_size * 2) == false)
{
return false;
}
}
*Stack->top = ele;
Stack->top++;
return Stack_OK;
}

/**
* @brief 栈_弹栈
*
* @param Stack
* @return Elemtype
*/
Elemtype Pop(struct my_Stack* Stack)
{
if(Stack_empty(Stack) == true)
{
printf("弹栈失败:这个栈已经是空的了.\n");
return ~(unsigned int)0/2;
}
else
{
Stack->top--;
return *Stack->top;
}
}

空栈弹栈的返回值 ~(unsigned int)0/2 是 int 的最大值——用一个”不可能出现的数”当错误码,调用方拿到它就知道弹栈失败了。除了 Push/Pop,还有 Stack_init(calloc 初始化)、Stack_new(realloc 扩容)、Stack_empty/Stack_fullStack_clear(top 指回 base)和 Stack_destory(free)一整套接口,全部配了 Doxygen 注释——这个习惯一直保留到了后来的 Print 项目。

表达式在内存里长什么样

一个 token 要么是数字,要么是运算符,用两个指针表示:

1
2
3
4
5
struct ele
{
char *p_opt;
double *p_num;
};

所有数字统一存进 double num[100],运算符存进 char opt[100],token 数组里只放指针。这样转后缀、求值的时候搬运的都是小小的 struct ele,不用拷贝数据本身。

预处理:把表达式洗干净

用户输入什么都有可能。入口函数 calc() 先做几件”洗数据”的活:

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
double calc(char *str)
{
double result = 0;
struct ele postfix_Expression[100];
memset(postfix_Expression, 0, sizeof(postfix_Expression));

char new_str[100];
memset(new_str, 0, sizeof(new_str));
new_str[0] = '0';
new_str[1] = '+';
strcpy(new_str+2, str);

for (int i = 0; i < sizeof(new_str); i++)
{
if(new_str[i] == '[' || new_str[i] == '{')
{
new_str[i] = '(';
}
else if(new_str[i]== ']' || new_str[i] == '}')
{
new_str[i] = ')';
}
}


str_find_exp_and_calc(new_str);
printf("str_find_exp_and_calc : %s\n", new_str);

mid_to_back(new_str, strlen(new_str), postfix_Expression);
result = caculate_four_arithmetic_operations(postfix_Expression);
// printf("result : %lf\n",result);

return result;
}
  • 开头拼一个 0+-1+2 变成 0-1+2,负号从”一元运算符”降级成普通的二元减号,后面的算法完全不用为它设计特判
  • 三种括号归一化{ [ 全换成 (} ] 全换成 )——对求值来说它们语义相同,没必要区别对待
  • 先算函数str_find_exp_and_calc 会把表达式里所有 sin(...)sqrt(...) 直接换成算好的数值(后面细讲),四则运算拿到的就永远是纯数字表达式

接下来拆 token。先把每个字符标记成”符号/非符号”的掩码数组 opt_idx,再把相邻的非符号位合并成一位——多位数字和小数点属于同一个数:

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
for(i = 0 ; i < len ; ++i)
{
if(str[i] == '[' || str[i] == '{')
{
str[i] = '(';
}
else if(str[i] == ']' || str[i] == '}')
{
str[i] = ')';
}

if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '^' || str[i] == '(' || str[i] == ')')
{
opt[count_opt] = str[i];
opt_idx[i] = 1;
count_opt++;
}
else
{
opt_idx[i] = 0;
}
}
//合并多余的0

for(int i = 0; i < 99; ++i)
{
if(opt_idx[i] == 0 && opt_idx[i+1] == 0)
{
for(int j = i; j < 99; ++j)
{
opt_idx[j] = opt_idx[j+1];
}
i--;
}
}

数字本体用 strtok+-*/^() 切开、atof 转 double:

1
2
3
4
5
6
p = strtok(str, "+-*/^()");
num[0] = atof(p);
while((p = strtok(NULL, "+-*/^()")))
{
num[count_num++] = atof(p);
}

最后把 num 数组和 opt 数组按掩码交错装进 struct ele 数组,中缀表达式就在内存里排好了队。

中缀转后缀

遍历中缀表达式的每个 token,规则只有四条:

  • 数字 → 直接加入结果
  • 左括号 ( → 直接入符号栈
  • 右括号 ) → 不断弹栈进结果,直到碰见左括号
  • 运算符 → 与栈顶比优先级:严格大于才入栈;否则不断弹栈进结果,直到能入栈为止
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
struct my_Stack Stack_calculate;
struct ele postfix_Expression[100];
ll count_postfix_idx = 0;

Stack_init(&Stack_calculate);
char opt_cal;
ll opt_temp_idx = 0;
char opt_temp[100];
char opt_top;

//初始化结构体数组为了防止后续引用报错
for(i = 0; i < 100; ++i)
{
postfix_Expression[i].p_num = NULL;
postfix_Expression[i].p_opt = NULL;
}

for (i = 0; i < max_idx; ++i)
{
if(infix_expression[i].p_num != NULL)
{
postfix_Expression[count_postfix_idx] = infix_expression[i];
count_postfix_idx++;
//printf("数字: %ld 加入到后缀表达式\n",*(postfix_Expression[count_postfix_idx].p_num));
}
else if(infix_expression[i].p_opt != NULL)
{
opt_cal = *infix_expression[i].p_opt;
if( opt_cal == '(')
{
Push(&Stack_calculate,opt_cal);
continue;
}
if( opt_cal != ')')
{
//先判断优先级 大于栈顶的元素就可以入栈 一开始是空栈哦
if(Stack_empty(&Stack_calculate) == true)
{
opt_top = ' ';//最低级的
}
else
{
opt_top = *(Stack_calculate.top-1);
}
if(Priority(opt_cal) > Priority(opt_top))
{
Push(&Stack_calculate,opt_cal);
}
else
{
//小于等于栈顶的元素的话,要一直弹栈
while(Priority(opt_cal) <= Priority(opt_top))
{
//弹到最后没有元素了直接入栈欸
if(Stack_empty(&Stack_calculate) == true || *(Stack_calculate.top-1) == '(')
{
break;
}
opt_top = Pop(&Stack_calculate);
opt_temp[opt_temp_idx] = opt_top;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
count_postfix_idx++;
opt_temp_idx++;
}
Push(&Stack_calculate,opt_cal);
}
}
else//如果是右括号
{
//由于要匹配左括号,要一直弹栈直到出现左括号
char char_tmp = 0;
while(char_tmp != '(')
{
char_tmp = Pop(&Stack_calculate);
if(char_tmp == '(')
{
break;
}
opt_temp[opt_temp_idx] = char_tmp;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
opt_temp_idx++;
count_postfix_idx++;
}
}
}
}
//弹出栈的所有元素
while(Stack_empty(&Stack_calculate) == false)
{
opt_top = Pop(&Stack_calculate);
opt_temp[opt_temp_idx] = opt_top;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
opt_temp_idx++;
count_postfix_idx++;
}

注意比较用的是严格大于:同优先级的运算符会先把栈里的弹出来、再让新的入栈,保证 8-3-2(8-3)-2 从左到右算——这是左结合。这里如果写成 >=,连续的减法除法就会算反。循环结束后把符号栈里剩的符号全部弹进结果,中缀就变成了后缀。

后缀求值:下标入栈

求值有个小障碍:栈的 Elemtypeint,要存的却是 double。把栈改成 double 也行,但这里的解法更轻:double 全放在 num_tmp 数组里,栈里只压下标。数字 token 到来时压的是它的下标;遇到运算符就弹两个下标,取数计算,结果追加到 num_tmp 尾部,再把新结果的”下标”压回去:

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
//记录储存的数组的最大值是多少,然后出栈之后就从这里开始
ll max_idx = count;
ll max_idx_count = 0;

count = 0;
for (int i = 0; i < 100; ++i)
{
if(postfix_Expression[i].p_num != NULL)
{
Push(&Stack_calculate,count);
count++;
continue;
}
if(postfix_Expression[i].p_opt != NULL)
{
ll num_1_idx = Pop(&Stack_calculate);
ll num_2_idx = Pop(&Stack_calculate);
switch (*postfix_Expression[i].p_opt)
{
case '^':
{
num_tmp[max_idx+max_idx_count] = pow(num_tmp[num_2_idx],num_tmp[num_1_idx]);
Push(&Stack_calculate,max_idx+max_idx_count);
max_idx_count++;
break;
}
case '+':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] + num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
max_idx_count++;
break;
}
case '-':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] - num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
max_idx_count++;
break;
}
case '*':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] * num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
max_idx_count++;
break;
}
case '/':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] / num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
max_idx_count++;
break;
}
default:
break;
}
continue;
}
}

有个容易翻车的细节:先弹出的是右操作数。减法、除法、幂都不满足交换律,num_2_idxnum_1_idx 的顺序反了,8/2 就变 2/8 了。全部 token 走完,栈里剩下的那个下标指向的就是最终答案。

数学函数:函数指针查找表 + 递归

sin(3.1415926/2) 这种怎么算?思路是在四则运算之前,先把表达式里的函数调用全部换成数值str_find_exp_and_calc 从左到右扫描,看到 ( 且前一个字符不是运算符也不是另一个 (——说明这个括号头上挂着函数名。函数名是倒着往回抠的,抠完把字符串反转回来;参数则用计数器做括号匹配:遇到 ( 加一、遇到 ) 减一,归零时正好是最外层右括号——不管参数里嵌了多少层括号都能完整抠出来。

15 个数学函数的”查找表”,是一串 strcmp 加函数指针:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef double (*math_fun)(double);
math_fun get_math_fun(const char *s)
{
if (strcmp(s, "sin") == 0)
{
return sin;
}
else if (strcmp(s, "cos") == 0)
{
return cos;
}
else if (strcmp(s, "tan") == 0)
{
return tan;
}
// ……sinh/cosh/tanh/asin/acos/atan/exp/log/log10/sqrt/ceil/floor 分支同构,略
else
{
return NULL;
}
}

参数表达式里可能还嵌着函数,所以直接递归调用 calc()

1
2
3
4
5
strcpy(str_temp, exp_strs[i]);
double temp = calc(exp_strs[i]);
strcpy(exp_strs[i], str_temp);

char *temp_result_str = double2str(get_math_fun(exp_funcs[i])(temp));

sin(1+sin(1+sin(1))) 就是这样一层层递归进去、一层层替换回来的。算出的结果替换回原字符串时还有个细节:负数结果要包成 (0-x),否则替换回去的一元负号会让后面的四则运算翻车:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(exp_strStuct.exp_results[i][0] == '-')
{
char *temp = exp_strStuct.exp_results[i];
exp_strStuct.exp_results[i] = (char *)malloc(sizeof(char) * (strlen(exp_strStuct.exp_results[i]) + 3));
memset(exp_strStuct.exp_results[i], 0, sizeof(char) * (strlen(exp_strStuct.exp_results[i]) + 3));

exp_strStuct.exp_results[i][0] = '(';
exp_strStuct.exp_results[i][1] = '0';
strcpy(exp_strStuct.exp_results[i] + 2, temp);
exp_strStuct.exp_results[i][strlen(exp_strStuct.exp_results[i])] = ')';

free(temp);
}
// printf("|temp|: %s\n", temp);
// printf("|exp_strStuct.exp_results[i]|: %s\n", exp_strStuct.exp_results[i]);

运行效果

main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include "calc.h"

int main()
{
char exp[100] = "1+2*3/4";
// char exp[100] = "(1.1+(1.1+(1.1+(1.1+(1.1+(1.1+1.1))))))";
// char exp[100] = "1+2*3/4+{1+[2*(1+1)]}+3";
// char exp[100] = "3+45/2+{7+[8*(3+1)]}-6";
// char exp[100] = "4*(3-2)+{8/[4*(2-1)]}+9";
// char exp[100] = "1+23/4+{5+[6*(2+1)]}-7";
// char exp[100] = "5/2+3*{2-[5/(2-1)]}+4";
// char exp[100] = "23-4/2+{1+[4*(3-1)]}+5";
// char exp[100] = "2.53-4.1/2.5+{1.3+[4.7*(3.2-1.1)]}+5.8";
// char exp[100] = "5.6/2.1+3.4*{2.8-[5.3/(2.2-1.1)]}+4.9";
// char exp[100] = "1+2*(3+4)+0.000000+(0-1.000000)+10.000000+1.000000+2.718282";
// char exp[100] = "1+2*(3+4)+sin(3.1415926/2)+cos(3.1415926)+sqrt(100)+log10(10)+exp(1)";
// char exp[100] = "1+sin(1+sin(1+sin(1+sin(1))))";
// char exp[100] = "sin[3.1415926/2]";
printf("%lf\n",calc(exp));
return 0;
}

测试用的表达式一直留在注释里,从整数四则、三种括号混用,到 sin/cos/sqrt/log10/exp 嵌套调用,就是这个项目能力范围的一份清单。

版本迭代

  • V1.0calc.c + My_Stack.c/.h 跑通主流程——双栈转后缀、下标入栈求值,配了一个”多文件编译并链接”的 .bat 脚本
  • V1.1:测试验证版,代码和 V1.0 基本一致,主要在换测试用例(比如 1/(9))做边界验证
  • V1.2:模块化整理——struct ele 和调试宏抽进 calc.h;新增 func_calc.c/.h 数学函数模块(函数指针表 + 括号匹配 + 递归求值);顺手修了 num[] 未初始化、掩码合并循环边界(50→99)两个小 bug

V1.2 完整代码

项目一共 7 个文件,main.c 已在上面贴出,其余 6 个按依赖顺序全部贴出。

My_Stack.h

My_Stack.h
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
#ifndef _My_Stack_H_
#define _My_Stack_H_

#include <stdio.h>
#include <stdlib.h>
#define Elemtype int

#define bool char

#define Stack_OK 0
#define true 1
#define false 0

#define init_element_num 100
#define init_error -1

typedef long int ll;

struct my_Stack
{
ll stack_size;
Elemtype* base;
Elemtype* top;
Elemtype* max;
};

bool Stack_init(struct my_Stack* Stack);
bool Stack_new(struct my_Stack* Stack, ll num);
bool Stack_destory(struct my_Stack* Stack);

ll Stack_get_len(struct my_Stack* Stack);
bool Stack_empty(struct my_Stack* Stack);
bool Stack_full(struct my_Stack* Stack);

void Stack_clear(struct my_Stack* Stack);
bool Push(struct my_Stack* Stack, Elemtype ele);

Elemtype Pop(struct my_Stack* Stack);

#endif

My_Stack.c

My_Stack.c
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
184
185
#include <stdio.h>
#include <stdlib.h>
#include "My_Stack.h"

/**
* @brief 栈_初始化
*
* @param Stack
* @return true
* @return false
*/
bool Stack_init(struct my_Stack* Stack)
{
Stack->base = (Elemtype *)calloc(sizeof(Elemtype),init_element_num);
if(Stack->base == NULL)
{
return init_error;
}
Stack->stack_size = init_element_num;
Stack->top = Stack->base;
Stack->max = Stack->base + init_element_num;
return Stack_OK;
}

/**
* @brief 栈_设置新的栈长度
*
* @param Stack
* @param num
* @return true
* @return false
*/
bool Stack_new(struct my_Stack* Stack, ll num)
{
Stack->base = (Elemtype *)realloc(Stack->base,sizeof(Elemtype) * num);
if(Stack->base == NULL)
{
return false;
}
Stack->stack_size = num;
Stack->max = Stack->base + num;
return Stack_OK;
}

/**
* @brief 栈_获取长度
*
* @param Stack
* @return ll
*/
ll Stack_get_len(struct my_Stack* Stack)
{
return Stack->stack_size;
}

/**
* @brief 栈_判断是否为空栈
*
* @param Stack
* @return true
* @return false
*/
bool Stack_empty(struct my_Stack* Stack)
{
if(Stack->top == Stack->base)
{
return true;
}
else
{
return false;
}
}


/**
* @brief 栈_判断是否为满栈
*
* @param Stack
* @return true
* @return false
*/
bool Stack_full(struct my_Stack* Stack)
{
if(Stack->top == Stack->max)
{
return true;
}
else
{
return false;
}
}

/**
* @brief 栈_清空栈
*
* @param Stack
*/
void Stack_clear(struct my_Stack* Stack)
{
Stack->top = Stack->base;
return ;
}

/**
* @brief ջ_ѹջ
*
* @param Stack
* @param ele
* @return true
* @return false
*/
bool Push(struct my_Stack* Stack, Elemtype ele)
{
if(Stack_full(Stack) == true)
{
if(Stack_new(Stack,Stack->stack_size * 2) == false)
{
return false;
}
}
*Stack->top = ele;
Stack->top++;
return Stack_OK;
}

/**
* @brief 栈_弹栈
*
* @param Stack
* @return Elemtype
*/
Elemtype Pop(struct my_Stack* Stack)
{
if(Stack_empty(Stack) == true)
{
printf("弹栈失败:这个栈已经是空的了.\n");
return ~(unsigned int)0/2;
}
else
{
Stack->top--;
return *Stack->top;
}
}

/**
* @brief 栈_销毁栈
*
* @param Stack
* @return true
* @return false
*/
bool Stack_destory(struct my_Stack* Stack)
{
Stack->top = Stack->base;
free(Stack->base);
Stack->stack_size = 0;
return Stack_OK;
}

/**
* @brief 测试代码
*
* @return int
*/
// int main()
// {
// struct my_Stack stack;
// Stack_init(&stack);
// Pop(&stack);
// Push(&stack, 123);
// printf("%d\n",Pop(&stack));
// Stack_clear(&stack);
// Push(&stack,456);
// Push(&stack,789);
// printf("Stack_len:%ld\n",Stack_get_len(&stack));
// Push(&stack,789);
// Push(&stack,789);
// Push(&stack,789);
// printf("Stack_len:%ld\n",Stack_get_len(&stack));
// Stack_destory(&stack);
// return 0;
// }

calc.h

calc.h
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
#ifndef _calc_H_
#define _calc_H_

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "My_Stack.h"
#include "func_calc.h"

#define cal_max_idx 100 //用于储存计算信息的最大数组

// #define input
#define details
#define details_Stack
#define details_array

struct ele
{
char *p_opt;
double *p_num;
};

double calc(char *str);

#endif

func_calc.h

func_calc.h
1
2
3
4
5
6
#ifndef _Func_calc_H_
#define _Func_calc_H_

char* str_find_exp_and_calc(char *s);

#endif

func_calc.c

func_calc.c
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "func_calc.h"
#include "calc.h"


char *str_rpl(char *s, const char *s1, const char *s2)
{
char *ptr;
while ((ptr = strstr(s, s1)) != NULL) /* 如果在s中找到s1 */
{
memmove(ptr + strlen(s2) , ptr + strlen(s1), strlen(ptr) - strlen(s1) + 1);
memcpy(ptr, &s2[0], strlen(s2));
}
return s;
}

void str_reverse(char* s)
{
char* left = s;
char* right = s + strlen(s) - 1;
while (left < right)
{
char tmp = *left;
*left = *right;
*right = tmp;

left++;
right--;
}
}

char* double2str(double num)
{
// double:8字节 2.3E-308 到 1.7E+308
static char str[21];
sprintf(str, "%lf", num);
return str;
}

double str2double(const char* str)
{
return atof(str);
}

typedef double (*math_fun)(double);
math_fun get_math_fun(const char *s)
{
if (strcmp(s, "sin") == 0)
{
return sin;
}
else if (strcmp(s, "cos") == 0)
{
return cos;
}
else if (strcmp(s, "tan") == 0)
{
return tan;
}
else if (strcmp(s, "sinh") == 0)
{
return sinh;
}
else if (strcmp(s, "cosh") == 0)
{
return cosh;
}
else if (strcmp(s, "tanh") == 0)
{
return tanh;
}
else if (strcmp(s, "asin") == 0)
{
return asin;
}
else if (strcmp(s, "acos") == 0)
{
return acos;
}
else if (strcmp(s, "atan") == 0)
{
return atan;
}
else if (strcmp(s, "exp") == 0)
{
return exp;
}
else if (strcmp(s, "log") == 0)
{
return log;
}
else if (strcmp(s, "log10") == 0)
{
return log10;
}
else if (strcmp(s, "sqrt") == 0)
{
return sqrt;
}
else if (strcmp(s, "ceil") == 0)
{
return ceil;
}
else if (strcmp(s, "floor") == 0)
{
return floor;
}
else
{
return NULL;
}
}

typedef struct
{
int exp_count;
char **exp_funcs;
char **exp_strs;
char **exp_results;
}exp_strStuctTypedef;

char* str_find_exp_and_calc(char *s)
{
char *ptr = s; //遍历整个字符串的指针

char exp_func[100] = {0}; //储存当前找到的表达式函数
int exp_func_i = 0; //当前找到的表达式函数数组的下标
char **exp_funcs = (char **)malloc(sizeof(char *) * 100); //储存所有找到的表达式函数
int exp_funcs_i = 0; //所有找到的表达式函数数组的下标
memset(exp_funcs, 0, sizeof(char *) * 100);

char exp_str[100] = {0}; //储存当前找到的表达式
int exp_str_i = 0; //当前找到的表达式数组的下标
char **exp_strs = (char **)malloc(sizeof(char *) * 100); //储存所有找到的表达式
int exp_strs_i = 0; //所有找到的表达式数组的下标
memset(exp_strs, 0, sizeof(char *) * 100);

// char exp_result[100] = {0}; //储存当前表达式的计算值
// int exp_result_i = 0; //当前找到的表达式计算值数组的下标
char **exp_results = (char **)malloc(sizeof(char *) * 100); //储存所有找到的表达式的计算值
// int exp_results_i = 0; //所有找到的表达式计算值数组的下标
// memset(exp_results, 0, sizeof(char *) * 100);

// printf("str: %s\n", s);
while (*ptr++)
{
if ((*ptr == '(') && (*(ptr - 1) != '(') && (*(ptr - 1) != '+') && (*(ptr - 1) != '-') && (*(ptr - 1) != '*') && (*(ptr - 1) != '/'))
{
// printf("find exp: ");
char *exp_func_ptr = ptr;
while(*exp_func_ptr--)
{
if((*exp_func_ptr != '+') && (*exp_func_ptr != '-') && (*exp_func_ptr != '*') && (*exp_func_ptr != '/') && (*exp_func_ptr != '('))
{
// putchar(*exp_func_ptr);
exp_func[exp_func_i++] = *exp_func_ptr;
}
else
{
exp_func[exp_func_i] = '\0';
exp_funcs[exp_funcs_i] = (char *)malloc(sizeof(char) * (exp_func_i + 1));

strcpy(exp_funcs[exp_funcs_i], exp_func);
str_reverse(exp_funcs[exp_funcs_i]);
exp_funcs_i++;

memset(exp_func, 0, 100);
exp_func_i = 0;

break;
}
}

int count_kuohao = -1;
char *sub_str_ptr = ptr + 1;
memset(exp_str, 0, 100);

do
{
// 括号匹配
if(*sub_str_ptr == ')')
{
count_kuohao++;
}
else if(*sub_str_ptr == '(')
{
count_kuohao--;
}

// 退出条件
if(count_kuohao != 0)
{
// putchar(*sub_str_ptr);
exp_str[exp_str_i++] = *sub_str_ptr;
}
else
{
exp_str[exp_str_i] = '\0';
// printf("find exp: |%s|\n", exp_str);
exp_strs[exp_strs_i] = (char *)malloc(sizeof(char) * (exp_str_i + 1));

strcpy(exp_strs[exp_strs_i], exp_str);
// printf("find exp: |%s|\n", exp_strs[exp_strs_i]);
exp_strs_i++;

memset(exp_str, 0, 100);
exp_str_i = 0;
break;
}

}while(*sub_str_ptr++);
}
}

for (int i = 0; i < exp_strs_i; i++)
{
char str_temp[100] = {0};
// 使用calc计算会对原来表达式进行修改
strcpy(str_temp, exp_strs[i]);
double temp = calc(exp_strs[i]);
strcpy(exp_strs[i], str_temp);

char *temp_result_str = double2str(get_math_fun(exp_funcs[i])(temp));
exp_results[i] = (char *)malloc(sizeof(char) * (strlen(temp_result_str) + 1));
strcpy(exp_results[i], temp_result_str);
}

exp_strStuctTypedef exp_strStuct;
exp_strStuct.exp_count = exp_strs_i;
exp_strStuct.exp_funcs = exp_funcs;
exp_strStuct.exp_strs = exp_strs;
exp_strStuct.exp_results = exp_results;

for (int i = 0; i < exp_strStuct.exp_count; i++)
{
// printf("find exp_func %s, parameters is %s, result is %s\n", exp_strStuct.exp_funcs[i], exp_strStuct.exp_strs[i], exp_strStuct.exp_results[i]);
char temp[100] = {0};
strcpy(temp, exp_strStuct.exp_funcs[i]);
strcat(temp, "(");
strcat(temp, exp_strStuct.exp_strs[i]);
strcat(temp, ")");
if(exp_strStuct.exp_results[i][0] == '-')
{
char *temp = exp_strStuct.exp_results[i];
exp_strStuct.exp_results[i] = (char *)malloc(sizeof(char) * (strlen(exp_strStuct.exp_results[i]) + 3));
memset(exp_strStuct.exp_results[i], 0, sizeof(char) * (strlen(exp_strStuct.exp_results[i]) + 3));

exp_strStuct.exp_results[i][0] = '(';
exp_strStuct.exp_results[i][1] = '0';
strcpy(exp_strStuct.exp_results[i] + 2, temp);
exp_strStuct.exp_results[i][strlen(exp_strStuct.exp_results[i])] = ')';

free(temp);
}
// printf("|temp|: %s\n", temp);
// printf("|exp_strStuct.exp_results[i]|: %s\n", exp_strStuct.exp_results[i]);
str_rpl(s, temp, exp_strStuct.exp_results[i]);

}


return s;
}


// int main()
// {
// // char str[100] = "1+2*(3+4)+sin(1+8+(2+3))+cos((2+3)*8+2*(3+4))";
// char str[100] = "1+2*(3+4)+sin(3.1415926)+cos(3.1415926)+sqrt(100)+log10(10)+exp(1)";
// exp_strStuctTypedef exp_strStuct = str_find_exp_and_calc(str);

// printf("result : %s\n", str);
// return 0;
// }

calc.c

calc.c
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "My_Stack.h"
#include "func_calc.h"
#include "calc.h"

int Priority(char ch)
{
switch(ch)
{
case '^':
return 3;
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}

bool mid_to_back(char *str, ll len, struct ele result[])
{
ll i;
ll count_num = 1;
ll count_opt = 0;
char *p;
double num[100] = {0};
char opt[100] = {'\0'};
long opt_idx[100] = {0};

ll count_num_idx = 0;
ll count_opt_idx = 0;
struct ele infix_expression[100];

//初始化idx数组
for (i = 0; i < sizeof(opt_idx)/sizeof(opt_idx[0]); ++i)
{
opt_idx[i] = -1;
}
//初始化中缀表达式的结构体数组
for(i = 0; i < 100; ++i)
{
infix_expression[i].p_num = NULL;
infix_expression[i].p_opt = NULL;
}

for(i = 0 ; i < len ; ++i)
{
if(str[i] == '[' || str[i] == '{')
{
str[i] = '(';
}
else if(str[i] == ']' || str[i] == '}')
{
str[i] = ')';
}

if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '^' || str[i] == '(' || str[i] == ')')
{
opt[count_opt] = str[i];
opt_idx[i] = 1;
count_opt++;
}
else
{
opt_idx[i] = 0;
}
}
//合并多余的0

for(int i = 0; i < 99; ++i)
{
if(opt_idx[i] == 0 && opt_idx[i+1] == 0)
{
for(int j = i; j < 99; ++j)
{
opt_idx[j] = opt_idx[j+1];
}
i--;
}
}
//找到最大的符号下标
ll max_idx = 0;
for(i = 0 ; i < 100 ; ++i)
{
if(opt_idx[i] == -1)
{
max_idx = i;
break;
}
}

//处理浮点数
p = strtok(str, "+-*/^()");
num[0] = atof(p);
while((p = strtok(NULL, "+-*/^()")))
{
num[count_num++] = atof(p);
}
#ifdef details
printf("获取所有的浮点数:\n");
for (i = 0; i < count_num; ++i)
{
printf("%f ",num[i]);
}
putchar('\n');
printf("\n获取所有的运算符:\n");
for (i = 0; i < strlen(opt); ++i)
{
printf("%c ",opt[i]);
}
putchar('\n');
putchar('\n');
#endif
// for (i = 0; i < max_idx; ++i)
// {
// printf("%ld ",opt_idx[i]);
// }
// putchar('\n');

//利用结构体数组将数字数组和操作符数组结合起来
for (i = 0; i < max_idx; ++i)
{
if(opt_idx[i] == 1)
{
infix_expression[i].p_num = NULL;
infix_expression[i].p_opt = &opt[count_opt_idx];
count_opt_idx++;
}
else if(opt_idx[i] == 0)
{
infix_expression[i].p_num = &num[count_num_idx];
infix_expression[i].p_opt = NULL;
count_num_idx++;
}
}

/*
count_num_idx = 0;
count_opt_idx = 0;
bool flag_a = true;
while(opt[count_opt_idx] != '\0' && count_num_idx < count_num)
{
// printf("%lf ",num[count_num_idx]);
// printf("%c ",opt[count_opt_idx]);

//注意开头就是括号的情况
if(opt[count_opt_idx] == '(')
{
while(opt[count_opt_idx] == '(')
{
infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
}
//左括号完后一定是一个数字
}

infix_expression[count_infix_idx].p_num = &num[count_num_idx];
infix_expression[count_infix_idx].p_opt = NULL;
count_num_idx++;
count_infix_idx++;

infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
if(opt[count_opt_idx] == ')' && flag_a == true)
{
infix_expression[count_infix_idx].p_num = &num[count_num_idx];
infix_expression[count_infix_idx].p_opt = NULL;
count_num_idx++;
count_infix_idx++;
flag_a == false;
}

//可能符号已经输出完了,但是还有最后一个数字没有输出出来
if(opt[count_opt_idx] == '\0')
{
infix_expression[count_infix_idx].p_num = &num[count_num_idx];
infix_expression[count_infix_idx].p_opt = NULL;
count_num_idx++;
count_infix_idx++;
}

if(opt[count_opt_idx] == '(')
{
while(opt[count_opt_idx] == '(')
{
infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
}
//左括号完后一定是一个数字
}

if(opt[count_opt_idx] == ')')
{
while(opt[count_opt_idx] == ')')
{
infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
}
//右括号完后一定是一个操作符
infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
//操作符完之后还可能是一堆左括号eg ((1+2)+(2+3))
while(opt[count_opt_idx] == '(')
{
infix_expression[count_infix_idx].p_num = NULL;
infix_expression[count_infix_idx].p_opt = &opt[count_opt_idx];
count_opt_idx++;
count_infix_idx++;
}
}
}
*/
//将结构体数组打印出来

#ifdef details
printf("转换完的中缀表达式如下:\n");
for (i = 0; i < max_idx; ++i)
{
if(infix_expression[i].p_num != NULL)
{
//printf("%d %lf NULL\n",i, *infix_expression[i].p_num);
printf("%lf ",*infix_expression[i].p_num);
}
if(infix_expression[i].p_opt != NULL)
{
//printf("%d NULL %c\n",i, *infix_expression[i].p_opt);
printf("%c ",*infix_expression[i].p_opt);
}
}
putchar('\n');
#endif
#ifdef details_Stack
printf("\n开始转换后缀表达式:\n");
#endif
struct my_Stack Stack_calculate;
struct ele postfix_Expression[100];
ll count_postfix_idx = 0;

Stack_init(&Stack_calculate);
char opt_cal;
ll opt_temp_idx = 0;
char opt_temp[100];
char opt_top;

//初始化结构体数组为了防止后续引用报错
for(i = 0; i < 100; ++i)
{
postfix_Expression[i].p_num = NULL;
postfix_Expression[i].p_opt = NULL;
}

for (i = 0; i < max_idx; ++i)
{
if(infix_expression[i].p_num != NULL)
{
postfix_Expression[count_postfix_idx] = infix_expression[i];
count_postfix_idx++;
//printf("数字: %ld 加入到后缀表达式\n",*(postfix_Expression[count_postfix_idx].p_num));
}
else if(infix_expression[i].p_opt != NULL)
{
opt_cal = *infix_expression[i].p_opt;
if( opt_cal == '(')
{
Push(&Stack_calculate,opt_cal);
#ifdef details_Stack
printf("符号: %c 入栈\n",opt_cal);
#endif
continue;
}
if( opt_cal != ')')
{
//先判断优先级 大于栈顶的元素就可以入栈 一开始是空栈哦
if(Stack_empty(&Stack_calculate) == true)
{
opt_top = ' ';//最低级的
}
else
{
opt_top = *(Stack_calculate.top-1);
#ifdef details_Stack
printf("符号: %c 出来作比较\n",opt_top);
#endif
}
if(Priority(opt_cal) > Priority(opt_top))
{
Push(&Stack_calculate,opt_cal);
#ifdef details_Stack
printf("符号: %c 入栈\n",opt_cal);
#endif
}
else
{
//小于等于栈顶的元素的话,要一直弹栈
while(Priority(opt_cal) <= Priority(opt_top))
{
//弹到最后没有元素了直接入栈欸
if(Stack_empty(&Stack_calculate) == true || *(Stack_calculate.top-1) == '(')
{
break;
}
opt_top = Pop(&Stack_calculate);
#ifdef details_Stack
printf("符号: %c 弹栈\n",opt_top);
#endif
opt_temp[opt_temp_idx] = opt_top;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
count_postfix_idx++;
opt_temp_idx++;
}
Push(&Stack_calculate,opt_cal);
#ifdef details_Stack
printf("符号: %c 入栈\n",opt_cal);
#endif
}
}
else//如果是右括号
{
#ifdef details_Stack
printf("右括号来了\n");
#endif
//由于要匹配左括号,要一直弹栈直到出现左括号
char char_tmp = 0;
while(char_tmp != '(')
{
char_tmp = Pop(&Stack_calculate);
#ifdef details_Stack
printf("符号: %c 弹栈\n",char_tmp);
#endif
if(char_tmp == '(')
{
break;
}
opt_temp[opt_temp_idx] = char_tmp;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
opt_temp_idx++;
count_postfix_idx++;
}
}
}
}
//弹出栈的所有元素
while(Stack_empty(&Stack_calculate) == false)
{
opt_top = Pop(&Stack_calculate);
#ifdef details_Stack
printf("符号: %c 弹栈\n",opt_top);
#endif
opt_temp[opt_temp_idx] = opt_top;
postfix_Expression[count_postfix_idx].p_opt = &opt_temp[opt_temp_idx];
postfix_Expression[count_postfix_idx].p_num = NULL;
opt_temp_idx++;
count_postfix_idx++;
}

//将转换好的内容重新输入到函数的参数地址上
for (i = 0; i < max_idx; ++i)
{
result[i].p_num = postfix_Expression[i].p_num;
result[i].p_opt = postfix_Expression[i].p_opt;
}
#ifdef details
//输出后缀表达式
printf("\n转换的后缀表达式如下:\n");
for (i = 0; i < max_idx; ++i)
{
if(postfix_Expression[i].p_num != NULL)
{
//printf("%d %lf NULL\n",i, *postfix_Expression[i].p_num);
printf("%lf ",*postfix_Expression[i].p_num);
continue;
}
else if(postfix_Expression[i].p_opt != NULL)
{
//printf("%d NULL %c\n",i, *postfix_Expression[i].p_opt);
printf("%c ",*postfix_Expression[i].p_opt);
continue;
}
}
putchar('\n');
#endif
//不能直接返回postfix_Expression,因为这是局部变量哦 warning:function returns address of local variable
Stack_clear(&Stack_calculate);
Stack_destory(&Stack_calculate);
return true;
}

double caculate_four_arithmetic_operations(struct ele* postfix_Expression)
{
struct my_Stack Stack_calculate;
Stack_init(&Stack_calculate);
//这里要定义一个数字下标数组,因为double类型数组和Elementype为int类型的数组冲突了
//打算后面用下标入栈
// double num_tmp[100] = {0};
double *num_tmp = (double*)malloc(sizeof(double)*100);
ll count = 0;
for(int i = 0; i < 100; ++i)
{
if(postfix_Expression[i].p_num != NULL)
{
num_tmp[count] = *postfix_Expression[i].p_num;
//printf("%lf ",num_tmp[count]);
count++;
}
}
//putchar('\n');
#ifdef details_Stack
printf("\n接下来开始用栈计算最终的结果\n");
#endif
//记录储存的数组的最大值是多少,然后出栈之后就从这里开始
ll max_idx = count;
ll max_idx_count = 0;

count = 0;
for (int i = 0; i < 100; ++i)
{
if(postfix_Expression[i].p_num != NULL)
{
Push(&Stack_calculate,count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",count,num_tmp[count]);
#endif
count++;
continue;
}
if(postfix_Expression[i].p_opt != NULL)
{
ll num_1_idx = Pop(&Stack_calculate);
ll num_2_idx = Pop(&Stack_calculate);
#ifdef details_Stack
printf("下标: [%ld]=%lf & [%ld]=%lf 弹栈\n",num_1_idx,num_tmp[num_1_idx],num_2_idx,num_tmp[num_2_idx]);
#endif
switch (*postfix_Expression[i].p_opt)
{
case '^':
{
num_tmp[max_idx+max_idx_count] = pow(num_tmp[num_2_idx],num_tmp[num_1_idx]);
Push(&Stack_calculate,max_idx+max_idx_count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",max_idx+max_idx_count,num_tmp[max_idx+max_idx_count]);
#endif
max_idx_count++;
break;
}
case '+':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] + num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",max_idx+max_idx_count,num_tmp[max_idx+max_idx_count]);
#endif
max_idx_count++;
break;
}
case '-':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] - num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",max_idx+max_idx_count,num_tmp[max_idx+max_idx_count]);
#endif
max_idx_count++;
break;
}
case '*':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] * num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",max_idx+max_idx_count,num_tmp[max_idx+max_idx_count]);
#endif
max_idx_count++;
break;
}
case '/':
{
num_tmp[max_idx+max_idx_count] = num_tmp[num_2_idx] / num_tmp[num_1_idx];
Push(&Stack_calculate,max_idx+max_idx_count);
#ifdef details_Stack
printf("下标: [%ld]=%lf 入栈\n",max_idx+max_idx_count,num_tmp[max_idx+max_idx_count]);
#endif
max_idx_count++;
break;
}
default:
break;
}
continue;
}
}
double result = num_tmp[Pop(&Stack_calculate)];
Stack_destory(&Stack_calculate);
free(num_tmp);
return result;
}

double calc(char *str)
{
double result = 0;
struct ele postfix_Expression[100];
memset(postfix_Expression, 0, sizeof(postfix_Expression));

char new_str[100];
memset(new_str, 0, sizeof(new_str));
new_str[0] = '0';
new_str[1] = '+';
strcpy(new_str+2, str);

for (int i = 0; i < sizeof(new_str); i++)
{
if(new_str[i] == '[' || new_str[i] == '{')
{
new_str[i] = '(';
}
else if(new_str[i]== ']' || new_str[i] == '}')
{
new_str[i] = ')';
}
}


str_find_exp_and_calc(new_str);
printf("str_find_exp_and_calc : %s\n", new_str);

mid_to_back(new_str, strlen(new_str), postfix_Expression);
result = caculate_four_arithmetic_operations(postfix_Expression);
// printf("result : %lf\n",result);

return result;
}