代码还添加了乘方的优先级,自行参考
一开始我写的只能输入个位数,后来想了好久才解决,主要是在判断是否为运算符后,若不是运算符,别急着入栈,用一个标记数组记着,若下一个字符还不是运算符,则利用strcat函数链接之前标记数组和这一个字符,直到下一个字符是运算符为止,才入栈。
至于负数的运算,则要判断是否连续两个都为运算符,且前一个运算符为‘(’后一个运算符为‘-’,若是就加个0入栈即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define M 10
#define add 10
/*字符栈*/
typedef struct
{
char *base;
int stacksize;
int top;
} sqstack;
int init(sqstack &s)
{
s.base = (char *)malloc(M * sizeof(char));
if (!s.base)
{
exit(-1);
}
s.top = 0;
s.stacksize = M;
return 1;
}
int push(sqstack &s, char e)
{
char *newbase;
if (s.top == s.stacksize)
{
newbase = (char *)realloc(s.base, (s.stacksize + add) * sizeof(char));
if (!newbase)
{
exit(-1);
}
s.base = newbase;
s.stacksize += add;
}
s.base[s.top++] = e;
return 1;
}
int pop(sqstack &s, char &e)
{
if (!s.top)
{
exit(-1);
}
e = s.base[--s.top];
return 1;
}
int Gettop(sqstack s, char &e)
{
if (!s.top)
{
exit(-1);
}
e = s.base[s.top - 1];
return 1;
}
/*操作数栈*/
typedef struct
{
float *base;
int top;
int stacksize;
} datastack;
int init_data(datastack &s)
{
s.base = (float *)malloc(M * sizeof(float));
if (!s.base)
{
exit(-1);
}
s.top = 0;
s.stacksize = M;
return 1;
}
int push_data(datastack &s, float e)
{
float *newbase;
if (s.top == s.stacksize)
{
newbase = (float *)realloc(s.base, (s.stacksize + add) * sizeof(float));
if (!newbase)
{
exit(-1);
}
s.base = newbase;
s.stacksize += add;
}
s.base[s.top++] = e;
return 1;
}
int pop_data(datastack &s, float &e)
{
if (!s.top)
{
exit(-1);
}
e = s.base[--s.top];
return 1;
}
int gettop_data(datastack s, float &e)
{
if (!s.top)
{
exit(-1);
}
e = s.base[s.top - 1];
return 1;
}
/*判断算符优先关系*/
char judge(char a, char b)
{
switch (a)
{
case '+':
if (b == '+' || b == '-' || b == ')' || b == '#')
{
return '>';
}
else
{
return '<';
}
case '-':
if (b == '+' || b == '-' || b == ')' || b == '#')
{
return '>';
}
else
{
return '<';
}
case '*':
if (b == '(' || b == '^')
{
return '<';
}
else
{
return '>';
}
case '/':
if (b == '(' || b == '^')
{
return '<';
}
else
{
return '>';
}
case '#':
if (b == '#')
{
return '=';
}
else if (b == ')')
{
return ' '; /*返回空值,为后面判断与'=''>''<'区分*/
}
else
{
return '<';
}
case '(':
if (b == ')')
{
return '=';
}
else if (b == '#')
{
return ' ';
}
else
{
return '<';
}
case ')':
if (b == '(')
{
return ' ';
}
else
{
return '>';
}
case '^':
if (b == '(')
{
return '<';
}
else
{
return '>';
}
default:
return ' ';
}
}
/*计算操作*/
float action(float a, char k, float b)
{
switch (k)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '^':
return pow(a, b);
default :
return 0.0;
}
}
/*判断运算符or操作数*/
int isysf(char c)
{
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#' || c == '^')
{
return 1;
}
return 0;
}
/*正片*/
float hehe(char *input)
{
sqstack optr;
datastack opnd;
float a, b, data, ku = 0;
int i = 0;
float ans;
int flag = 0; /*用作判断是否为负数*/
char e, x, y;
char tempdata[20], ap[2] = {'#', '\0'};
char *c;
init(optr);
init_data(opnd);
push(optr, '#');
c = strcat(input, ap);
strcpy(tempdata, "\0");
Gettop(optr, e);
while (c[i] != '#' || e != '#')
{
if (!isysf(c[i]))
{
ap[0] = c[i];
strcat(tempdata, ap);
i++;
if (isysf(c[i]))
{
data = atof(tempdata);
push_data(opnd, data);
strcpy(tempdata, "\0");
}
flag = 0;
}
else
{
if (flag) /*若连续两个都是运算符*/
{
Gettop(optr, y);
if (y == '(' && c[i] == '-') /*判断输入是否为负数*/
{
push_data(opnd, ku); /*0入操作数栈*/
push(optr, c[i]);
i++;
}
else /*连续两个都是运算符却不是负数*/
{
switch (judge(e, c[i]))
{
case '<':
push(optr, c[i]);
i++;
break;
case '=':
pop(optr, x);
i++;
break;
case '>':
pop(optr, e);
pop_data(opnd, a);
pop_data(opnd, b);
push_data(opnd, action(b, e, a));
break;
}
}
}
else
{
switch (judge(e, c[i]))
{
case '<':
push(optr, c[i]);
i++;
break;
case '=':
pop(optr, x);
i++;
break;
case '>':
pop(optr, e);
pop_data(opnd, a);
pop_data(opnd, b);
push_data(opnd, action(b, e, a));
break;
}
}
flag = 1;
}
Gettop(optr, e);
}
gettop_data(opnd, ans);
return ans;
}
int main()
{
float a;
char c[1111];
printf("****************************************************************\n");
printf("\n加法:+ 减法:- 乘法:* 除法:/ 乘方:^ \n");
printf("\n数值可为任意实数,输入负数必须用括号()括起来,结果保留2位小数\n\n");
printf("****************************************************************\n\n");
while (1)
{
printf("输入表达式:\n");
gets(c);
a = hehe(c);
printf("表达式的值为:%.2f\n", a);
}
return 0;
}