对于栈的概念这里不做再多说明,先进后出,后进先出。这里用到两个栈,计算栈和操作栈
输入一个算数表达式(中序表达式)之后,从头遍历,如果是数字的话直接放到一个计算栈中准备计算,如果是符号的话按照符号的权值对符合进行进出操作栈操作
代码如下(运行环境VS2015版本)
#include
#include
#include
#define STRING_MAX_LENGTH 10
#define STACK_MAX_LENGTH 20
#pragma warning(disable:4996)
#define BIG 1
#define SMALL_OR_EQUAL 0
#define EMPTY 1
#define IS_NUM 1
#define IS_CHAR 0
#define EXP_lENGTH 100
#define TABLE {'#', 0, 0}, { '(',1,8 }, { '^',7,6 }, { '*',5,4 }, { '/',5,4 }, { '+',3,2 }, { '-',3,2 }, { ')',8,1 }
//操作符
struct Operator{
char operator;//操作符
int isp;//栈顶权值
int icp;//栈外权值
};
//栈
struct Stack{
char item[STACK_MAX_LENGTH][STRING_MAX_LENGTH];//栈内的每一项元素
int length;//栈的长度
int topPoint;//栈的顶元素标号
};
//实例化一个栈
void inntStack(struct Stack *stack){
stack->length = 0;
stack->topPoint = -1;
}
//进栈
int pushItme(struct Stack *stack,char *item) {
stack->topPoint++;
strcpy(stack->item[stack->topPoint], item);
stack->length++;
return 0;
}
//出栈
int popItem(struct Stack *stack) {
stack->topPoint--;
stack->length--;
return 0;
}
//取栈顶元素
char * topItem(struct Stack *stack){
return stack->item[stack->topPoint];
}
//打印输出栈内所有元素
void printStack(struct Stack *stack) {
int i;
for (i = 0; i < stack->length; i++) {
printf("%s\n",stack->item[i]);
}
}
//判断是字符还是数字
int isCharOrNum(char ch) {
if (ch >= '0' && ch <= '9') {
return IS_NUM;
}
else
return IS_CHAR;
}
//比较栈内栈外两个操作符的权值大小 ch1为栈内的 ch2为栈外的
int compareOperator(char ch1,char ch2) {
int i;
int j;
struct Operator operator_table[8] = { TABLE };
for ( i = 0; i < 8; i++){
if (ch1==operator_table[i].operator){
break;
}
}
for ( j = 0; j < 8; j++){
if (ch2==operator_table[j].operator){
break;
}
}
if (operator_table[i].isp>operator_table[j].icp){
return BIG;
}
//栈内小于等于栈外
if (operator_table[i].isp < operator_table[j].icp|| operator_table[i].isp == operator_table[j].icp) {
return SMALL_OR_EQUAL;
}
}
//判断一个栈是否为空
int isEmpty(struct Stack *stack) {
if (stack->length ==0 ) {
return EMPTY;
}
else {
return 0;
}
}
int getTowItems(double *first, double *second, struct Stack *stack1) {
if (stack1->length<2){
return 0;
}
else{
*first = atof(stack1->item[stack1->length - 2]);
*second = atof(stack1->item[stack1->length - 1]);
//popItem(stack1);
//popItem(stack1);
return 1;
}
}
//进行计算
double calculate(double first, double second, char op) {
double answer=0.0;
switch (op){
case '+':
answer = first + second;
break;
case '-':
answer = first - second;
break;
case '*':
answer = first * second;
break;
case '/':
answer = first / second;
break;
case '^':
break;
default:
break;
}
return answer;
}
//算数表达式放入Stack中(暂时测试用)
void putStringExpIntoStack(char *stringExp, struct Stack* stack,struct Stack* stack1) {
int i = 0;
int j = 0;
double first = 0.0;
double second = 0.0;
double tempAnswer = 0.0;
int n = strlen(stringExp);//表达式内所有符号的数量
char temp[STRING_MAX_LENGTH];//temp数组
char tempAnswerStr[STRING_MAX_LENGTH];
char operateTemp[STRING_MAX_LENGTH];
char charArrayExp[EXP_lENGTH];//用字符数组承接字符串
char *topStackchar; //栈顶操作符
for (i =0; i
charArrayExp[i] = *(stringExp++);
}
i = 0;
while (i
if (isCharOrNum(charArrayExp[i]) == IS_CHAR) {
temp[0] = charArrayExp[i];
temp[1] = '\0';
if (isEmpty(stack)==EMPTY){
pushItme(stack, temp);//如果是操作符号,则进操作符号栈内
}
else {
topStackchar = topItem(stack);
//如果操作栈外的大于等于操作栈内 则进操作栈
if (compareOperator(topStackchar[0], charArrayExp[i])==SMALL_OR_EQUAL){
temp[0] = charArrayExp[i];
temp[1] = '\0';
pushItme(stack, temp);
}
//如果操作栈栈内元素大于 则操作符出操作栈
if (compareOperator(topStackchar[0], charArrayExp[i]) == BIG) {
strcpy(operateTemp,topItem(stack));//取得运算符号
popItem(stack);
//如果能计算则进行计算
if (getTowItems(&first,&second,stack1)){ //***如果从数字栈内可以取到数字元素的话
tempAnswer = calculate(first, second, operateTemp[0]);
sprintf(tempAnswerStr, "%lf", tempAnswer);//double转string
if (operateTemp[0]!='('&&operateTemp[0]!=')'){
popItem(stack1);
popItem(stack1);
pushItme(stack1, tempAnswerStr);
}
}
while (isEmpty(stack) != EMPTY&&compareOperator(topStackchar[0], charArrayExp[i]) == BIG){
strcpy(operateTemp, topItem(stack));
popItem(stack);
if (getTowItems(&first, &second, stack1)) { //如果从数字栈内可以取到数字元素的话
tempAnswer = calculate(first, second, operateTemp[0]);
sprintf(tempAnswerStr, "%lf", tempAnswer);//double转string
if (operateTemp[0] != '('&&operateTemp[0] != ')') {
popItem(stack1);
popItem(stack1);
pushItme(stack1, tempAnswerStr);
}
}
}
temp[0] = charArrayExp[i];
temp[1] = '\0';
pushItme(stack, temp);
}
}
i++;
continue;
}
if (isCharOrNum(charArrayExp[i]) == IS_NUM) {
j = 0;
temp[j] = charArrayExp[i];//先把数字放在用于字符串处理的字符数组[0]里面
j++;
i++;
while (i
temp[j] = charArrayExp[i];
j++;
i++;
}
temp[j] = '\0';
pushItme(stack1, temp);//放入计算栈中
continue;
}
}
while (isEmpty(stack) != EMPTY) {
strcpy(temp, topItem(stack));
popItem(stack);
if (getTowItems(&first, &second, stack1)) { //如果从数字栈内可以取到数字元素的话
tempAnswer = calculate(first, second, temp[0]);
sprintf(tempAnswerStr, "%lf", tempAnswer);//double转string
if (temp[0] != '('&&temp[0] != ')') {
popItem(stack1);
popItem(stack1);
pushItme(stack1, tempAnswerStr);
}
}
}
}
int main(void) {
char stringExp[EXP_lENGTH];//算数表达式(中序表达式)
struct Stack *stackOperate; //用于 中转 算数操作符的栈
struct Stack *stackCalculate;//用于进行算数计算的栈
struct Operator operator_table[8] = {TABLE};
stackOperate =(struct Stack*) malloc(sizeof(struct Stack));//为栈分配一段内存空间
stackCalculate = (struct Stack*) malloc(sizeof(struct Stack));//为栈分配一段内存空间
inntStack(stackOperate);
inntStack(stackCalculate);
printf("请输入一个算数表达式:(注意小括号要用英文的小括号不然不识别哦)\n");
scanf("%s", &stringExp);//输入一个算数表达式
putStringExpIntoStack(stringExp, stackOperate,stackCalculate);
//printf("这是符号栈:\n");
//printStack(stackOperate);
printf("--------------\n");
//printf("这是数字栈:\n");
printf("结果是:");
printStack(stackCalculate);
printf("--------------\n");
getchar();
getchar();
return 0;
}