Skip to content

Instantly share code, notes, and snippets.

@imfing
Created July 21, 2017 03:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imfing/c4ad0cbecb3773697a73c81be8d3bacb to your computer and use it in GitHub Desktop.
Save imfing/c4ad0cbecb3773697a73c81be8d3bacb to your computer and use it in GitHub Desktop.
Parse math expression with c
/**
*Math Expression Parser
*
*Author: Fing
*
*First Created: 2015.12.13
*
*/
#include "stdio.h"
/*Try with minimal libarary usage*/
int powr(int x, int n); //计算x^n
int isNum(char ch); //判断一个字符是否是数字
int isOp(char ch); //判断是否为运算符
int isPar(char ch); //判断是否为括号
int cmpPrio(char a, char b); // 比较运算符的优先级 a>b?
int ch2num(char ch); //将字符转换为数字
int getNum(char input[], int i); //取多位数字
void pushNum(int numb[], int top, int number); //向数字栈中添加数字
int popNum(int numb[], int top); //数字栈中弹出数字
void pushOp(char op[], int top, char operat); //向运算符栈中添加运算符
char popOp(char op[], int top); //运算符栈中弹出运算符
int calc(int a, int b, char c); //计算两个数字
int Calculate(char input[], int length); //计算结果
char op[50] = { '\0' }; //存放运算符
int num[50] = { '\0' }; //存放数字
int op_top = -1;
int num_top = -1;
int leftBracketCount = 0; //左括号计数
int rightBracketCount = 0; //有括号计数
int opCount = 0; //运算符计数
int numCount = 0; //数字计数
int main()
{
char input[50];
int length = 1;
input[0] = getchar();
int i;
for (i = 1; i <= 50; i++)
{
input[i] = getchar();
length++;
if (input[i] == 10) break;
}
length--;
printf("= %d\n", Calculate(input, length));
getchar(); getchar();
}
//幂运算
int powr(int x, int n)
{
int i;
int result = 1;
for (i = 1; i <= n; i++)
result *= x;
return result;
}
//判断是否是数字
int isNum(char ch)
{
if (ch >= '0' && ch <= '9') return 1;
else return 0;
}
//判断是否是运算符
int isOp(char ch)
{
if (ch >= '+' || ch == '-' || ch == '*' || ch == '/') return 1;
else return 0;
}
//判断是否是括号
int isPar(char ch)
{
if (ch == '(' || ch == ')') return 1;
else return 0;
}
//比较运算符的优先级
int cmpPrio(char a, char b)
{
if (a == '*' || a == '/') return 1;
else return 0;
}
//字符->数字
int ch2num(char ch)
{
return (ch - '0');
}
//转化多位数字
int getNum(char input[], int i)
{
int j, count;
count = 1;
int result = 0;
for (j = i + 1; j<50; j++)
{
if (isNum(input[j])) count++;
else break;
}
for (j = i; j < i + count; j++)
{
result = result + ch2num(input[j])*powr(10, count - (j - i + 1));
}
return result;
}
//压入数字
void pushNum(int num[], int top, int number)
{
num[top + 1] = number;
num_top++;
}
//弹出数字
int popNum(int numb[], int top)
{
int t;
t = numb[top];
numb[top] = '\0';
num_top--;
return t;
}
//压入运算符
void pushOp(char op[], int top, char operat)
{
op[top + 1] = operat;
op_top++;
}
//弹出运算符
char popOp(char op[], int top) //运算符栈中弹出运算符
{
char t;
t = op[top];
op[top] = '\0';
op_top--;
return t;
}
//计算两个数字
int calc(int a, int b, char c)
{
switch (c)
{
case '+': return a + b; break;
case '-': return a - b; break;
case '*': return a*b; break;
case '/': return a / b; break;
default: break;
}
}
//计算
int Calculate(char input[], int length)
{
int i;
//遍历
for (i = 0; i<length; i++)
{
if (isNum(input[i])) //如果是数字,读取数字,入栈
{
int j;
pushNum(num, num_top, getNum(input, i));
for (j = i; j<length; j++)
{
if (!isNum(input[j])) //不是数字,改变循环起点
{
i = j - 1;
break;
}
}
numCount++; //数字计数++
}
else if (isOp(input[i])) //如果是运算符,判断优先级,计算栈顶两个数字
{
if (op_top>0) //如果有运算符,与上一个运算符比较
{
if (!isPar(op[op_top])) //如果上一个不是括号,则比较
{
if (cmpPrio((input[i]), op[op_top])) //优先级高的话,入栈
{
pushOp(op, op_top, input[i]);
}
else //否则计算栈顶两个数字,再将input入栈
{
int a, b;
b = popNum(num, num_top);
a = popNum(num, num_top);
pushNum(num, num_top, calc(a, b, popOp(op, op_top)));
pushOp(op, op_top, input[i]);
}
}
else //如果上一个是括号的话,
{
if (input[i] == '-' && input[i - 1] == '(') //负数的判断
{
pushNum(num, num_top, 0); //在栈顶插入0
pushOp(op, op_top, input[i]); //在栈顶压入减号
}
else
{
pushOp(op, op_top, input[i]);
}
}
}
else //如果前一个没有运算符了
{
pushOp(op, op_top, input[i]);
}
}
else if (isPar(input[i])) //如果是括号的话
{
if (input[i] == '(') //如果是左括号,直接进栈
{
pushOp(op, op_top, input[i]);
//leftBracketCount++;
}
else //右括号的情况
{
int j = op_top;
while (op[j] != '(') //遍历,计算
{
int a, b;
b = popNum(num, num_top);
a = popNum(num, num_top);
pushNum(num, num_top, calc(a, b, popOp(op, op_top)));
j--;
}
char c;
c = popOp(op, op_top); //弹出左边括号
//leftBracketCount--;
}
}
//int m;
//for (m = 0; m <= op_top; m++)
// printf("%c ", op[m]);
////printf(" %d",op_top);
//printf("\n");
//for (m = 0; m <= num_top; m++)
// printf("%d ", num[m]);
////printf(" %d", num_top);
//printf("\n");
}
int k;
for (k = op_top; k >= 0; k--)
{
int a, b;
b = popNum(num, num_top);
a = popNum(num, num_top);
pushNum(num, num_top, calc(a, b, popOp(op, op_top)));
}
return num[0];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment