c语言计算任意表达式(含括号)
时间: 2023-08-10 13:04:34 浏览: 91
表达式求解 数据结构
实现计算任意表达式的方法有很多种,其中一种比较常见的方法是通过将中缀表达式转换成后缀表达式,然后通过栈来计算后缀表达式的值。
以下是一个简单的实现方法:
1. 定义一个操作数栈和一个操作符栈。
2. 从左到右遍历表达式中的每个元素:
a. 如果是数字,则将其压入操作数栈。
b. 如果是左括号,则将其压入操作符栈。
c. 如果是右括号,则弹出操作符栈中的元素直到遇到左括号,并将这些操作符依次应用于操作数栈中弹出的两个元素,将结果压回操作数栈。
d. 如果是运算符,则比较其与操作符栈顶元素的优先级:
i. 如果优先级高于栈顶元素,则将其压入操作符栈。
ii. 否则,将操作符栈顶元素弹出并应用于操作数栈中弹出的两个元素,直到该运算符的优先级高于栈顶元素。
3. 当表达式遍历完后,依次弹出操作符栈中的元素并应用于操作数栈中弹出的两个元素,直到操作符栈为空。最终操作数栈中的唯一元素即为表达式的值。
以下是一个示例代码,实现了以上算法:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// 定义栈结构体
typedef struct {
int top;
int capacity;
double *array;
} Stack;
// 初始化栈
Stack* createStack(int capacity) {
Stack *stack = (Stack*) malloc(sizeof(Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (double*) malloc(capacity * sizeof(double));
return stack;
}
// 判断栈是否为空
int isEmpty(Stack *stack) {
return stack->top == -1;
}
// 判断栈是否已满
int isFull(Stack *stack) {
return stack->top == stack->capacity - 1;
}
// 入栈操作
void push(Stack *stack, double item) {
if (isFull(stack)) {
printf("Stack Overflow!\n");
} else {
stack->array[++stack->top] = item;
}
}
// 出栈操作
double pop(Stack *stack) {
if (isEmpty(stack)) {
printf("Stack Underflow!\n");
return -1;
} else {
return stack->array[stack->top--];
}
}
// 获取栈顶元素
double peek(Stack *stack) {
if (isEmpty(stack)) {
printf("Stack Underflow!\n");
return -1;
} else {
return stack->array[stack->top];
}
}
// 获取运算符优先级
int getPriority(char op) {
switch(op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:
return 0;
}
}
// 中缀表达式转后缀表达式
char* infixToPostfix(char *infix) {
int len = strlen(infix);
char *postfix = (char*) malloc((len+1) * sizeof(char));
int i, j = 0;
Stack *stack = createStack(len);
for (i = 0; i < len; i++) {
if (isdigit(infix[i])) {
// 如果是数字,直接输出
postfix[j++] = infix[i];
} else if (infix[i] == '(') {
// 如果是左括号,入栈
push(stack, infix[i]);
} else if (infix[i] == ')') {
// 如果是右括号,弹出栈中元素直到遇到左括号
while (!isEmpty(stack) && peek(stack) != '(') {
postfix[j++] = pop(stack);
}
if (!isEmpty(stack) && peek(stack) == '(') {
pop(stack);
}
} else {
// 如果是运算符,弹出栈中优先级高于或等于该运算符的元素
while (!isEmpty(stack) && getPriority(infix[i]) <= getPriority(peek(stack))) {
postfix[j++] = pop(stack);
}
push(stack, infix[i]); // 将该运算符入栈
}
}
// 将栈中剩余的元素弹出
while (!isEmpty(stack)) {
postfix[j++] = pop(stack);
}
postfix[j] = '\0';
free(stack->array);
free(stack);
return postfix;
}
// 计算后缀表达式的值
double evaluatePostfix(char *postfix) {
int len = strlen(postfix);
int i;
Stack *stack = createStack(len);
for (i = 0; i < len; i++) {
if (isdigit(postfix[i])) {
// 如果是数字,将其转换成实际值并入栈
int num = 0;
while (isdigit(postfix[i])) {
num = num * 10 + (int)(postfix[i] - '0');
i++;
}
push(stack, (double)num);
i--;
} else {
// 如果是运算符,弹出栈中两个元素进行计算,并将结果入栈
double op2 = pop(stack);
double op1 = pop(stack);
double result;
switch(postfix[i]) {
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '*':
result = op1 * op2;
break;
case '/':
result = op1 / op2;
break;
case '^':
result = pow(op1, op2);
break;
default:
result = 0;
}
push(stack, result);
}
}
double result = pop(stack);
free(stack->array);
free(stack);
return result;
}
int main() {
char *infix = "(1+2)*3-4/5^2";
char *postfix = infixToPostfix(infix);
printf("Infix expression: %s\n", infix);
printf("Postfix expression: %s\n", postfix);
printf("Result: %f\n", evaluatePostfix(postfix));
free(postfix);
return 0;
}
```
该代码可以计算包括括号在内的任意表达式,并支持加减乘除和乘方运算。需要注意的是,由于该代码使用了栈来存储中间结果,所以在计算复杂表达式时需要考虑栈的容量限制。
阅读全文