math/calculate.c

205 lines
5.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//参考文章https://blog.csdn.net/lei20172017/article/details/116404682
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include<windows.h>
#define MAX_SIZE 1000
/*定义一个运算符栈*/
typedef struct {
char Operator[MAX_SIZE];
int top;
} OptorStack;
/*定义一个操作数栈*/
typedef struct {
double Operand[MAX_SIZE];
int top;
} OpndStack;
/*初始化运算符栈*/
void InitOptor(OptorStack *S) {
S->top = -1;
}
/*初始化操作数栈*/
void InitOpnd(OpndStack *S) {
S->top = -1;
}
/*运算符出栈*/
int PopOptor(OptorStack *S,int *recall,char *errmsg) {
if(S->top==-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
S->top--;
return 1;
}
/*操作数出栈*/
int PopOpnd(OpndStack *S,int *recall,char *errmsg) {
if(S->top==-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
S->top--;
return 1;
}
/*运算符入栈*/
int PushOptor(OptorStack *S,char ch,int *recall,char *errmsg) {
if(S->top==MAX_SIZE-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
S->top++;
S->Operator[S->top]=ch;
return 1;
}
/*操作数入栈*/
int PushOpnd(OpndStack *S,double ch,int *recall,char *errmsg) {
if(S->top==MAX_SIZE-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
S->top++;
S->Operand[S->top]=ch;
return 1;
}
/*取运算符栈栈顶元素*/
char GetOptor(OptorStack *S,int *recall,char *errmsg) {
if(S->top==-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
return S->Operator[S->top];
}
/*取操作数栈栈顶元素*/
double GetOpnd(OpndStack *S,int *recall,char *errmsg) {
if(S->top==-1) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
return S->Operand[S->top];
}
/*表达式运算函数*/
double Calculate(double a,double b,char op,int *recall,char *errmsg) {
double result;
if(op=='+') result=a+b;
if(op=='-') result=a-b;
if(op=='*') result=a*b;
if(op=='/') { //要防止除数为0
if(b==0) {
*recall=-1;
strcpy(errmsg,"Wrong input.The divisor is not 0");
return -1;
}
result=a/b;
}
return result; //返回结果result
}
int change(char ch) {
switch(ch) {
case '+':
return 0;
case '-':
return 1;
case '*':
return 2;
case '/':
return 3;
case '(':
return 4;
case ')':
return 5;
case '#':
return 6;
}
}
/*定义一个算符优先关系矩阵*/
char cmp[7][8]= {">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<=?",">>>>?>>","<<<<<?="};
/*算符比较函数,返回优先级:>或<或=*/
int Compare(char ch1,char ch2,int *recall,char *errmsg) {
if(cmp[change(ch1)][change(ch2)]=='?') {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return -1;
}
return cmp[change(ch1)][change(ch2)];
}
/*检查函数,用来检查输入的表达式的操作数和运算符的合法性*/
int Check(char *S,int len) {
int i;
for(i=0; i<len; i++) {
if(S[i]>='0'&&S[i]<='9')continue;
if(S[i]=='('||S[i]==')'||S[i]=='*'||S[i]=='/'||S[i]=='+'||S[i]=='-'||S[i]=='.')continue;
return 0;
}
return 1;
}
void calculate(char *expre,int *recall,char *errmsg,double *answer) {
SetConsoleOutputCP(65001);
char opd[9999]; //opd用来存操作数
int len;
OptorStack Optor;
OpndStack Opnd;
InitOptor(&Optor);
InitOpnd(&Opnd);
PushOptor(&Optor,'#',recall,errmsg);
len = strlen(expre);
int kk=0;
for(int i=0;i<len;i++){
if(expre[len]>='0'&&expre[len]<='9')continue;
else kk=1;
}
if(kk==0){
*recall=-1;
strcpy(errmsg,"you should make sure this is a expression.");
return;
}
if (Check(expre,len) == 0) {
*recall=-1;
strcpy(errmsg,"Wrong input.");
return;
}
int i,j=0,k=0;
double x,y;
expre[len] = '#'; //在expre数组后加个#结尾标志
for (i=0; i<=len; i++) {
if ((expre[i]>='0' && expre[i]<='9') || expre[i] == '.') {
opd[k++] = expre[i]; //将数字字符存入操作数数组opd中
j = 1;
continue;
}
if(j) {
opd[k] = '\0';
PushOpnd(&Opnd,atof(opd),recall,errmsg);
j=0;
k=0;
}
switch (Compare(GetOptor(&Optor,recall,errmsg),expre[i],recall,errmsg)) { //比较运算符栈的栈顶运算符和运算符expre[i]的优先级
case '<':
PushOptor(&Optor,expre[i],recall,errmsg);
break;
case '=':
PopOptor(&Optor,recall,errmsg);
break;
case '>':
y = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg);
x = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg);
PushOpnd(&Opnd,Calculate(x,y,GetOptor(&Optor,recall,errmsg),recall,errmsg),recall,errmsg);
PopOptor(&Optor,recall,errmsg);
i--;
break;
default:break;
}
}
if(recall==-1)return;
*answer = GetOpnd(&Opnd,recall,errmsg);
}