c语言——表达式的计算

来源:互联网 发布:大学送礼给老师知乎 编辑:程序博客网 时间:2024/05/18 18:53

#include "stack.h" //提供栈及其基本操作函数
#include "mymath.h" //提供阶乘函数
#include <string.h>#include <math.h>#define BUFFSIZE 128#define CHARSIZE 10#define PI 3.141593#define E 2.718282#define PUSH_OPE_CON (Stack_Top(&operator) == '(' && buff[i] != ')') || (Stack_Top(&operator) == '[' && buff[i] != ']') || (dif = Judge_OPE(buff[i]) - Judge_OPE(Stack_Top(&operator))) > 1//运算符压入栈条件(压入的符号优先级大于上一个符号的优先级)#define SUPPLE_NUM if((last != NUM) && (buff[i] == '+' || buff[i] == '-')) { Push_Stack(&data, 0); } //填充数字0#define OPE_WORK_CON Stack_Top(&operator) != '(' && Stack_Top(&operator) != '[' //运算符执行运算条件#define POP_OPE_CON1 buff[i] == ')' && Stack_Top(&operator) == '(' //运算符弹出条件1()#define POP_OPE_CON2 buff[i] == ']' && Stack_Top(&operator) == '[' //运算符弹出条件2[]#define CLEAR_DOT if(dot == DOT) { dot = NUL; dot_num = 0; } //制空小数点标记符#define FUN_WORK_CON Judge_OPE(Stack_Top(&operator)) == FUN //函数执行条件typedef enum{ENT, NUL, BRR, SBR, ERR, ADD, SUB, PAS, REM, CHA, MUL, DIV, NUM, POW, OPE, FUN, DOT, SBL, BRL} status; //各类符合标识及其优先级static char buff[BUFFSIZE];static char chars[CHARSIZE];void Exit() //-e 退出{if(strncmp(buff, "-e", 2) == 0)exit(1);}status Help() //-h 帮助信息{if(strncmp(buff, "-h", 2) == 0) {printf(" Hi! The calculator supports:\n");printf("\tcalculate -- + , - , % , * , / , ^ , [ ](round numbers) , !(factorial)\n");printf("\tconstant --- pi(3.141593), e(2.718282), pr(the last result)\n");printf("\tfunction --- sin(), cos(), tan(), arcsin(), arccos(), arctan(), ln(), lg(), exp()\n");printf("\tps:\n");printf("\t I. -h help to use; -e exit\n");printf("\t II. pr's initial value is 0\n");printf("\tIII. while you input by mistake, the calculator will be exited\n");return PAS;}elsereturn ERR;}void Input() //输入表达式{memset(buff, 0, BUFFSIZE);printf("Welcome to use the calculator:\n\t");fgets(buff, BUFFSIZE, stdin);Exit();printf("=\n");}status Judge_Type(char c) //判断字符类型{if(c >= '0' && c <= '9')return NUM;else if(c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '(' || c == ')' || c == '%' ||c == '[' || c == ']' || c == '\n')return OPE;else if(c == '.')return DOT;else if((c >= 'a' && c <= 'z') || c == '!')return CHA;elsereturn ERR;}status Judge_OPE(char c) //判断运算符{if(c == '\n') return ENT;if(c == '+') return ADD;if(c == '-') return SUB;if(c == '%') return REM;if(c == '*') return MUL;if(c == '/') return DIV;if(c == '^') return POW;if(c == '[') return SBL;if(c == ']') return SBR;if(c == '(') return BRL;if(c == ')') return BRR;else return FUN;}float OPE_Work(float x, float y, status jud) //运算符执行{switch(jud){case ADD: return x + y;case SUB: return x - y;case REM: return fmod(x, y);case MUL: return x * y;case DIV: return x / y;case POW: return powf(x, y);}}void Dispose_CHA(stack *data, stack *ope) //判断函数和常数{if(strncmp(chars, "exp", 3) == 0)Push_Stack(ope, 'e');else if(strncmp(chars, "sin", 3) == 0)Push_Stack(ope, 's');else if(strncmp(chars, "cos", 3) == 0)Push_Stack(ope, 'c');else if(strncmp(chars, "tan", 3) == 0)Push_Stack(ope, 't');else if(strncmp(chars, "arcsin", 6) == 0)Push_Stack(ope, 'S');else if(strncmp(chars, "arccos", 6) == 0)Push_Stack(ope, 'C');else if(strncmp(chars, "arctan", 6) == 0)Push_Stack(ope, 'T');else if(strncmp(chars, "ln", 2) == 0)Push_Stack(ope, 'n');else if(strncmp(chars, "lg", 2) == 0)Push_Stack(ope, 'g');else if(strncmp(chars, "!", 1) == 0)Push_Stack(ope, 'f');else if(strncmp(chars, "pi", 2) == 0)Push_Stack(data, PI);else if(strncmp(chars, "e", 1) == 0)Push_Stack(data, E);}float FUN_Work(char c, float x) //函数执行{if(c == 'e') return exp(x);if(c == 's') return sin(x);if(c == 'c') return cos(x);if(c == 't') return tan(x);if(c == 'S') return asin(x);if(c == 'C') return acos(x);if(c == 'T') return atan(x);if(c == 'n') return log(x);if(c == 'g') return log10(x);if(c == 'f') return Factorial((int)x);}float Calculate(float prev) //表达式计算{stack data; //存储数字的栈stack operator; //存储字符的栈assert(Init_Stack(&data) == true);assert(Init_Stack(&operator) == true);memset(chars, 0, CHARSIZE);status this, last = NUL;status dot = NUL;int dot_num = 0;int dif;int i = 0, j = 0;while(1) {this = Judge_Type(buff[i]);if(this == CHA) { //非运算符字符提取chars[j] = buff[i];j++;i++;}if(this != CHA && last == CHA) { //非运算符字符的处理if(strncmp(chars, "pr", 2) == 0) {Push_Stack(&data, prev);}else {Dispose_CHA(&data, &operator);}memset(chars, 0, CHARSIZE);j = 0;}if(this == NUM) {float n;if(last == NUM && dot == NUL) { //记录多位数数字n = Pop_Stack(&data) * 10;if(n >= 0) {n = n + (buff[i] - '0');}else {n = n - (buff[i] - '0');}}else if(dot == DOT) { //记录小数点后小数dot_num++;n = Pop_Stack(&data);if(n >= 0) {n = n + (buff[i] - '0') * pow(0.1, dot_num);}else {n = n - (buff[i] - '0') * pow(0.1, dot_num);}}else { //记录个位数整数n = buff[i] - '0';}Push_Stack(&data, n);i++;}if(this == OPE) {CLEAR_DOT;if(Stack_Occupy(&operator) != EMPTY) {if(PUSH_OPE_CON) { //字符压入SUPPLE_NUM;Push_Stack(&operator, buff[i]);i++;}else if(OPE_WORK_CON) {float n;if(FUN_WORK_CON) { //函数执行n = FUN_Work(Pop_Stack(&operator), Pop_Stack(&data));}else { //运算符执行n = OPE_Work(Pop_Stack(&data), Pop_Stack(&data), Judge_OPE(Pop_Stack(&operator)));}Push_Stack(&data, n);}else if(POP_OPE_CON1) {Pop_Stack(&operator);i++;}else if(POP_OPE_CON2) {Pop_Stack(&operator);int n = (int)Pop_Stack(&data);Push_Stack(&data, n);i++;}}else {if(buff[i] != '\n') { //第一个字符压入SUPPLE_NUM;Push_Stack(&operator, buff[i]);i++;}else break;}}if(this == DOT) { //标记小数点dot = DOT;i++;}if(this == ERR) { //错误输入退出printf("input error!\n");exit(0);}last = this;}printf("\t%f\n", Stack_Top(&data));return Pop_Stack(&data);}int main(){float prev = 0;while(1) {Input();if(Help() == ERR) {prev = Calculate(prev);}}}
原创粉丝点击