表达式计算建议看一下《数据结构》,先转换为逆波兰表达式,然后再计算。
当然用字符串匹配也是可以的,但是这样复杂度会比较高,
匹配最里面的括号有一个方法就是寻找第一个右括号,和这个右括号对应的左括号合起来就是最里面的括号。
当然我给你一个逆波兰表达式的代码吧,可以解决你的问题,有点长,300多行:
#include
#include
#include
#include
#define ElemItem Item
#define SUCCEED 1
#define ERROR 0
#define MAXLENGTH 20
struct Item{
int type; //0表示单目运算符,1表示双目运算符,2表示数字
double num; //如果是数字就保存在这里
char oper[MAXLENGTH]; //如果是运算符就保存在这里
}nullItem;
typedef struct SNode{
ElemItem data;
SNode *next;
}*Stack;
struct QNode{
ElemItem data;
QNode *next;
};
struct Queue{
QNode *front;
QNode *rear;
};
void initStack(Stack *s){
*s = NULL;
}
void push(Stack *s, ElemItem e){
SNode *p = (SNode*)malloc(sizeof(SNode));
p->data = e;
p->next = *s;
*s = p;
}
int pop(Stack *s, ElemItem *e = NULL){
if(*s == NULL){
return ERROR;
}
if(e != NULL){
*e = (*s)->data;
}
SNode *p = *s;
*s = (*s)->next;
free(p);
return SUCCEED;
}
ElemItem getSData(Stack s){
if(s == NULL){
return nullItem;
}
return s->data;
}
void initQueue(Queue *q){
q->front = NULL;
q->rear = NULL;
}
void in(Queue *q, ElemItem e){
QNode* p = (QNode*)malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
if(q->rear != NULL){
q->rear->next = p;
}
q->rear = p;
if(q->front == NULL){
q->front = p;
}
}
int out(Queue *q, ElemItem *e){
if(q->front == NULL){
return ERROR;
}
*e = q->front->data;
QNode *p = q->front;
q->front = q->front->next;
free(p);
return SUCCEED;
}
ElemItem getQData(Queue q){
if(q.front == NULL){
return nullItem;
}
return q.front->data;
}
int getPriority(char *a){
if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0)
return 1;
if(strcmp(a, "*") == 0 || strcmp(a, "/") == 0)
return 2;
if(strcmp(a, "^") == 0)
return 3;
if(strcmp(a, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
|| strcmp(a, "ln") == 0 || strcmp(a, "exp") == 0 \
|| strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
return 4;
return -1;
}
int getCombination(char *a){ //1表示左结合,0表示右结合
if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0 || strcmp(a, "*") == 0 || strcmp(a, "/") == 0 || strcmp(a, "^") == 0)
return 1;
if(strcmp(a, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
|| strcmp(a, "ln") == 0 || strcmp(a, "exp") == 0 \
|| strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
return 0;
return -1;
}
int getOrder(char *a){ //0表示单目,1表示双目
if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0 || strcmp(a, "*") == 0 || strcmp(a, "/") == 0 || strcmp(a, "^") == 0)
return 1;
if(strcmp(a, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
|| strcmp(a, "ln") == 0 || strcmp(a, "exp") == 0 \
|| strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
return 0;
return -1;
}
double getResult0(char *oper, double a1){
if(strcmp(oper, "+") == 0)
return a1;
if(strcmp(oper, "-") == 0)
return -a1;
if(strcmp(oper, "sin") == 0)
return sin(a1);
if(strcmp(oper, "cos") == 0)
return cos(a1);
if(strcmp(oper, "tan") == 0)
return tan(a1);
if(strcmp(oper, "ln") == 0)
return log(a1);
if(strcmp(oper, "exp") == 0)
return exp(a1);
if(strcmp(oper, "arcsin") == 0)
return asin(a1);
if(strcmp(oper, "arccos") == 0)
return acos(a1);
if(strcmp(oper, "arctan") == 0)
return atan(a1);
return 0;
}
double getResult1(char *oper, double a1, double a2){
if(strcmp(oper, "+") == 0)
return a1+a2;
if(strcmp(oper, "-") == 0)
return a1-a2;
if(strcmp(oper, "*") == 0)
return a1*a2;
if(strcmp(oper, "/") == 0)
return a1/a2;
if(strcmp(oper, "^") == 0)
return pow(a1,a2);
return 0;
}
double calculate(char *expression){
//对表达式信息初步读取
int length = strlen(expression);
Queue firstExp;
initQueue(&firstExp);
int flag = -1; //0表示数字,1表示运算符,2表示函数
char tmp[MAXLENGTH] = {'\0'};
for(int i=0; i
if(expression[i] != ' '){
if((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.'){
if(flag == 1 || flag == 2){
Item item;
item.type = getOrder(tmp);
strcpy(item.oper, tmp);
in(&firstExp, item);
flag = 0;
tmp[0] = '\0';
}
if(flag == -1){
flag = 0;
}
}else{
if(expression[i] >= 'a' && expression[i] <= 'z'){
if(flag == 0){
Item item;
item.type = 2;
item.num = strtod(tmp, NULL);
in(&firstExp, item);
flag = 2;
tmp[0] = '\0';
}else if(flag == 1){
Item item;
item.type = getOrder(tmp);
strcpy(item.oper, tmp);
in(&firstExp, item);
flag = 2;
tmp[0] = '\0';
}else if(flag == 2 && getOrder(tmp) != -1){
Item item;
item.type = getOrder(tmp);
strcpy(item.oper, tmp);
in(&firstExp, item);
tmp[0] = '\0';
}
if(flag == -1){
flag = 2;
}
}else{
if(flag == 0){
Item item;
item.type = 2;
item.num = strtod(tmp, NULL);
in(&firstExp, item);
flag = 1;
tmp[0] = '\0';
}else if(flag == 2){
Item item;
item.type = getOrder(tmp);
strcpy(item.oper, tmp);
in(&firstExp, item);
flag = 1;
tmp[0] = '\0';
}else if(flag == 1){
Item item;
item.type = getOrder(tmp);
strcpy(item.oper, tmp);
in(&firstExp, item);
tmp[0] = '\0';
}
if(flag == -1){
flag = 1;
}
}
}
int l = strlen(tmp);
if(l < MAXLENGTH-1){
tmp[l] = expression[i];
tmp[l+1] = '\0';
}
//printf("first runing\n");
}
}
if(flag == 0){
Item item;
item.type = 2;
item.num = strtod(tmp, NULL);
in(&firstExp, item);
}else{
Item item;
item.type = 1;
strcpy(item.oper, tmp);
in(&firstExp, item);
}
tmp[0] = '\0';
//printf("first end\n");
/*Item i;
while(out(&firstExp, &i)){
if(i.type == 2){
printf("%lf\n", i.num);
}else{
printf("%s\n", i.oper);
}
}*/
//生成后缀表达式
int frontHasNum = 0; //最开始有无数字,0表示无数字,1表示有数字,如果最开始无数字,则第一个运算符降为单目运算符
Stack operStack;
initStack(&operStack);
Queue secondExp;
initQueue(&secondExp);
Item firstItem;
while(out(&firstExp, &firstItem)){
if(firstItem.type == 2){
frontHasNum = 1;
in(&secondExp, firstItem);
}else{
if(strcmp(firstItem.oper, "(") == 0){
frontHasNum = 0;
push(&operStack, firstItem);
}else if(strcmp(firstItem.oper, ")") == 0){
frontHasNum = 1;
Item t;
while(strcmp(getSData(operStack).oper, "(") != 0){
if(!pop(&operStack, &t))
break;
in(&secondExp, t);
//printf("second 1 while\n");
}
pop(&operStack);
}else{
Item t;
while((getPriority(firstItem.oper) < getPriority(getSData(operStack).oper)) \
|| (getPriority(firstItem.oper)==getPriority(getSData(operStack).oper) && getCombination(getSData(operStack).oper)==1)){
if(!pop(&operStack, &t))
break;
in(&secondExp, t);
//printf("second 2 while\n");
}
if(frontHasNum == 0){
frontHasNum = 1;
firstItem.type = 0;
}
push(&operStack, firstItem);
}
}
//printf("second runing\n");
}
while(pop(&operStack, &firstItem)){
in(&secondExp, firstItem);
//printf("second in runing\n");
}
//printf("second end\n");
/*Item i2;
while(out(&secondExp, &i2)){
if(i2.type == 2){
printf("%lf\n", i2.num);
}else{
printf("%s\n", i2.oper);
}
}*/
//计算
Stack startCalculate;
initStack(&startCalculate);
Item startItem;
while(out(&secondExp, &startItem)){
if(startItem.type == 2){
push(&startCalculate, startItem);
}else{
if(startItem.type == 0){
Item a;
pop(&startCalculate, &a);
a.num = getResult0(startItem.oper, a.num);
push(&startCalculate, a);
}else if(startItem.type == 1){
Item a1,a2;
pop(&startCalculate, &a2);
pop(&startCalculate, &a1);
Item a;
a.type = 2;
a.num = getResult1(startItem.oper, a1.num, a2.num);
push(&startCalculate, a);
}
}
//printf("calculating\n");
}
Item result;
pop(&startCalculate, &result);
return result.num;
}
int main(int argc, char *argv[]){
char exp[200] = {'\0'};
if(argc != 2){
printf("输入表达式:\n");
//scanf("%s", exp);
gets(exp);
}else{
strcpy(exp, argv[1]);
}
printf("计算结果为:%lf\n", calculate(exp));
return 0;
}
运行后直接输入算式就可以了。