字符串表达式的计算:栈的使用是其中的基础,其核心是正确分析出程序进行逻辑;
其中需要注意的问题:1.读到右括号需要计算到左括号;
2.优先级问题,先乘除后加减
栈的基本操作:初始化,压栈,弹栈就不赘述了。
对于字符串表达式的计算:有一个注意就是要创建两个栈,一个存放运算符号,一个存储数字。
判定数字:pass
int isNumber(char c) {
if (c >= '0' && c <= '9') return 1;
return 0;
}
局部计算:
1.当进行局部计算时,对于栈顶为左括号,直接弹出再进行计算
2.取出一个运算符,两个运算数,注意数字顺序
3.将计算结构压回数字栈
void cal_loc(stackPtr head) {
if (head->dataC[head->topC] == '(') {
popC(head);
return;
}
printf("int:");
PrintI(head);
putchar('n');
printf("char:");
PrintC(head);
putchar('n');
int a = popI(head);
int b = popI(head);
char c = popC(head);
printf("c==%c ", c);
int res = 0;
switch (c) {
case'*':
res = a * b;
break;
case'/':
res = (double)b / a;
break;
case'+':
res = a + b;
break;
case'-':
res = b - a;
break;
}
pushI(head, res);
printf("res = %d a=%d ,b=%dn", res, a, b);
}
主体计算函数:
1.判断数字,还得注意是非个位数的情况;并且因为优先级的问题以及栈空只剩下一个运算符的情况,我们直接判断,对于优先级:*或/直接进行计算,对于加减就交给读到右侧括号的while来进行计算。与凡老师代码不同,优先级的判断交给后边数字。
(举栗子:当出现(1+2*3)的情况,要计算*,但是得先读入后边的3才可以计算,剩下(1+6)就交给后边‘)’的判断while来计算,所以将数字存入之后再判断优先级才是明智之举。
2.对于符号:‘(、 ‘+、-、*、/’ 直接压栈
‘)’ 标志着进行一轮计算,注意要使用while,否则计算不彻底
int calculate(stackPtr head,char* str) {
for (int i = 0; i < strlen(str);i++ ) {
char temp = str[i];
if (isNumber(temp)) {
int j = i;
int sum = 0;
while (isNumber(str[j]) && jdataC[head->topC] == '*' || head->dataC[head->topC] == '/') cal_loc(head);
else if (head->topC == -1 && head->topI!=0) cal_loc(head);//有可能直接先只压一个数字。
}
else {
switch (temp) {
case'(':
pushC(head, temp);
break;
case')':
while(head->dataC[head->topC]!='(' && head->topI!=0) cal_loc(head);
popC(head);
break;
case '*':
pushC(head, temp);
break;
case '/':
pushC(head, temp);
break;
case'+':
pushC(head, temp);
break;
case'-':
pushC(head, temp);
break;
}
}
}
if (head->topC != -1) cal_loc(head);
return popI(head);
}
运行截图:
完整代码:
#include#include #include typedef struct { char dataC[20]; int dataI[20]; int topC,topI; }*stackPtr, stack; stackPtr InitStack() { stackPtr head = (stackPtr)malloc(sizeof(stack)); head->topC = -1; head->topI = -1; return head; } void pushC(stackPtr head, char c) { if (head->topC >= 18) { printf("no space"); return; } head->topC++; head->dataC[head->topC] = c; } char popC(stackPtr head) { char tempchar = head->dataC[head->topC]; head->topC--; return tempchar; } void pushI(stackPtr head, int c) { if (head->topI >= 18) { printf("no space"); return; } head->topI++; head->dataI[head->topI] = c; } int popI(stackPtr head) { int tempint = head->dataI[head->topI]; head->topI--; return tempint; } int isNumber(char c) { if (c >= '0' && c <= '9') return 1; return 0; } void PrintC(stackPtr head) { if (head->topC == -1) return; for (int i = head->topC; i >= 0; i--) { printf("%c ", head->dataC[i]); } } void PrintI(stackPtr head) { if (head->topI == -1) return; for (int i = head->topI; i >= 0; i--) { printf("%d ", head->dataI[i]); } } void cal_loc(stackPtr head) { if (head->dataC[head->topC] == '(') { popC(head); return; } printf("int:"); PrintI(head); putchar('n'); printf("char:"); PrintC(head); putchar('n'); int a = popI(head); int b = popI(head); char c = popC(head); printf("c==%c ", c); int res = 0; switch (c) { case'*': res = a * b; break; case'/': res = (double)b / a; break; case'+': res = a + b; break; case'-': res = b - a; break; } pushI(head, res); printf("res = %d a=%d ,b=%dn", res, a, b); } int calculate(stackPtr head,char* str) { for (int i = 0; i < strlen(str);i++ ) { char temp = str[i]; if (isNumber(temp)) { int j = i; int sum = 0; while (isNumber(str[j]) && j dataC[head->topC] == '*' || head->dataC[head->topC] == '/') cal_loc(head); else if (head->topC == -1 && head->topI!=0) cal_loc(head); } else { switch (temp) { case'(': pushC(head, temp); break; case')': while(head->dataC[head->topC]!='(' && head->topI!=0) cal_loc(head); popC(head); break; case '*': pushC(head, temp); break; case '/': pushC(head, temp); break; case'+': pushC(head, temp); break; case'-': pushC(head, temp); break; } } } if (head->topC != -1) cal_loc(head); return popI(head); } void Test() { stackPtr head = InitStack(head); char* tempExpression = "(21+2-1)*6"; printf("result = %d ", calculate(head, tempExpression)); } int main() { Test(); return 0; }



