Created
July 21, 2017 03:48
-
-
Save imfing/c4ad0cbecb3773697a73c81be8d3bacb to your computer and use it in GitHub Desktop.
Parse math expression with c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*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