// 思路:将常用的中缀表达式转化为逆波兰式(后缀表达式,即符号在两个数字后面,便于计算机识别)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct _numstack
{
double data;
struct _numstack *pre;
} numStack; // 数字栈
typedef struct _opstack
{
char ope;
struct _opstack *pre;
} opStack; // 符号栈
typedef struct _head
{
numStack *numTop;
opStack *opTop;
int i;
} Stack; // 指示栈顶和标记是否多位数
Stack *iniStack(Stack *p); // 初始化栈
void pushNum(Stack *head, char a); // 将字符转化为数字,并压入数字栈
void pushOp(Stack *head, char op); // 将符号压入符号栈
double popNum(Stack *head); // 将数字从数字栈弹出
char popOp(Stack *head); // 将符号从符号栈弹出
void count(Stack *head); // 计算
int isNum(char a); // 判断字符是数字还是符号
char compare(char a, char b); // 比较符号优先度,返回'>''<''='
int main()
{
printf("please input:\n");
char ch[25];
int i = 0;
for (i = 0; i <= 25; i++)
{
ch[i] = '#';
}
fgets(ch, 25, stdin);
Stack *head;
head = iniStack(head);
char e = '#';
for (i = 0; i <= 25; i++)
{
if (isNum(ch[i]) == 1)
{
pushNum(head, ch[i]);
head->i = 1;
}
else
{
head->i = 0;
if (head->opTop == NULL)
{
pushOp(head, ch[i]);
}
else if (ch[i] == ')')
{
pushOp(head, ch[i]);
count(head);
}
else
{
e = compare(ch[i], head->opTop->ope);
if (e == '>')
{
pushOp(head, ch[i]);
}
else if (e == '<')
{
if (head->opTop->ope != '(')
{
count(head);
}
pushOp(head, ch[i]);
if (head->opTop->ope == '=')
{
printf("%.3f", head->numTop->data);
break;
}
}
}
}
}
return 0;
}
int isNum(char a)
{
if (a == '+' || a == '-' || a == '*' || a == '/' || a == '(' || a == ')' || a == '^' || a == '=')
{
return 0;
}
else
{
return 1;
}
}
Stack *iniStack(Stack *p)
{
p = malloc(sizeof(Stack));
p->numTop = NULL;
p->opTop = NULL;
p->i = 0;
}
void pushNum(Stack *head, char a)
{
if (head->i != 1)
{
numStack *p = malloc(sizeof(numStack));
if (!p)
{
printf("ERROR");
exit(1);
} // 以防内存满的保险处理
p->pre = head->numTop;
head->numTop = p;
p->data = (int)(a - 48) / 1.0;
}
else
{
head->numTop->data *= 10;
head->numTop->data += (int)(a - 48) / 1.0;
}
}
void pushOp(Stack *head, char a)
{
opStack *p = malloc(sizeof(opStack));
if (!p)
{
printf("ERROR");
exit(1);
}
p->pre = head->opTop;
head->opTop = p;
p->ope = a;
}
double popNum(Stack *head)
{
double i = head->numTop->data;
numStack *p = head->numTop;
head->numTop = head->numTop->pre;
free(p);
return i;
}
char popOp(Stack *head)
{
char i = head->opTop->ope;
opStack *p = head->opTop;
head->opTop = head->opTop->pre;
free(p);
return i;
}
char compare(char a, char b)
{
char operator[] = { '+',
'-',
'*',
'/',
'^',
'(',
')',
'=' };
int x = 0, y = 0;
char levelTable[8][8] = {
{'>', '>', '<', '<', '<', '>', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>', '>'},
{'>', '>', '>', '>', '>', '>', '>', '>'},
{'>', '>', '>', '>', '>', '>', ' ', '>'},
{'<', '<', '<', '<', '<', ' ', '<', '>'},
{'<', '<', '<', '<', '<', '<', '<', '<'}}; // 制作二维数组,将两个符号坐标化再判断优先度
for (x = 0; x < 8; x++)
{
if (operator[x] == a)
{
break;
}
}
for (y = 0; y < 8; y++)
{
if (operator[y] == b)
{
break;
}
}
return levelTable[x][y];
}
void count(Stack *head)
{
char op = '#';
double down, up, sum;
numStack *p = NULL;
int i = 0;
if (head->opTop->ope == ')')
{
i = 1;
} // 如果从反括号开始运算,就是要把整个括号算完,即头括号也要删去,故做一标记i
while (head->numTop->pre != NULL)
{
if (head->opTop->ope == '(')
{
break;
}
op = popOp(head);
if (op != '(' && op != ')')
{
b = head->numTop->data;
p = head->numTop;
head->numTop = head->numTop->pre;
free(p);
a = head->numTop->data;
switch (op)
{
case '+':
sum = a + b;
break;
case '-':
sum = a - b;
break;
case '*':
sum = a * b;
break;
case '/':
sum = a / b;
break;
case '^':
sum = pow(a, b);
break;
}
head->numTop->data = sum;
}
}
if (i == 1)
{
op = popOp(head);
} // 运算结束后,head->opTop恰好指在头括号处
}
自我感觉写的很烂,
参考文章数据结构-C描述-堆栈-简单计算器_c语言使用堆栈写简单计算器编程代码-CSDN博客
还有这个码龄居然是按照注册年份算的。。。。