赞
踩
设计一个表达式求值器,能够解析和计算由数字、运算符和括号组成的算术表达式。要求实现基本的四则运算,如加、减、乘、除,并处理运算符的优先级和括号。
1. 使用栈作为数据结构来处理运算符和操作数的优先级。
2. 实现表达式的解析算法,将输入的字符串转换为内部表示形式,如逆波兰表示法。
3. 设计求值算法,根据运算符的优先级和操作数的顺序进行计算。
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
-
- #define MAX 100
-
- typedef struct {
- int top;
- char items[MAX];
- } Stack;
-
- void initStack(Stack* s) {
- s->top = -1;
- }
-
- int isEmpty(Stack* s) {
- return (s->top == -1);
- }
-
- int isFull(Stack* s) {
- return (s->top == MAX - 1);
- }
-
- void push(Stack* s, char value) {
- if (!isFull(s)) {
- s->items[++(s->top)] = value;
- }
- else {
- printf("栈满了\n");
- }
- }
-
- char pop(Stack* s) {
- if (!isEmpty(s)) {
- return s->items[(s->top)--];
- }
- else {
- printf("栈为空\n");
- return 0;
- }
- }
-
- char peek(Stack* s) {
- if (!isEmpty(s)) {
- return s->items[s->top];
- }
- else {
- return '\0';
- }
- }
-
- int precedence(char op) {
- switch (op) {
- case '+':
- case '-':
- return 1;
- case '*':
- case '/':
- return 2;
- default:
- return 0;
- }
- }
-
- int isOperator(char ch) {
- return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
- }
-
- void infixToPostfix(char* infix, char* postfix) {
- Stack s;
- initStack(&s);
- int k = 0;
-
- for (int i = 0; infix[i] != '\0'; i++) {
- if (isdigit(infix[i])) {
- while (isdigit(infix[i])) {
- postfix[k++] = infix[i++];
- }
- postfix[k++] = ' ';
- i--;
- }
- else if (infix[i] == '(') {
- push(&s, infix[i]);
- }
- else if (infix[i] == ')') {
- while (!isEmpty(&s) && peek(&s) != '(') {
- postfix[k++] = pop(&s);
- postfix[k++] = ' ';
- }
- pop(&s);
- }
- else if (isOperator(infix[i])) {
- while (!isEmpty(&s) && precedence(peek(&s)) >= precedence(infix[i])) {
- postfix[k++] = pop(&s);
- postfix[k++] = ' ';
- }
- push(&s, infix[i]);
- }
- }
-
- while (!isEmpty(&s)) {
- postfix[k++] = pop(&s);
- postfix[k++] = ' ';
- }
- postfix[k - 1] = '\0';
- }
-
- int evaluatePostfix(char* postfix) {
- Stack s;
- initStack(&s);
- int i = 0;
- while (postfix[i] != '\0') {
- if (isdigit(postfix[i])) {
- int num = 0;
- while (isdigit(postfix[i])) {
- num = num * 10 + (postfix[i++] - '0');
- }
- push(&s, num);
- }
- else if (isOperator(postfix[i])) {
- int val2 = pop(&s);
- int val1 = pop(&s);
- switch (postfix[i]) {
- case '+': push(&s, val1 + val2); break;
- case '-': push(&s, val1 - val2); break;
- case '*': push(&s, val1 * val2); break;
- case '/': push(&s, val1 / val2); break;
- }
- i++;
- }
- else {
- i++;
- }
- }
- return pop(&s);
- }
-
- int main() {
- char infix[MAX], postfix[MAX];
- printf("Enter an infix expression: ");
- fgets(infix, MAX, stdin);
- infix[strcspn(infix, "\n")] = '\0';
-
- infixToPostfix(infix, postfix);
- printf("Postfix expression: %s\n", postfix);
-
- int result = evaluatePostfix(postfix);
- printf("Result: %d\n", result);
-
- return 0;
- }

typedef struct {
int top;
char items[MAX];
} Stack;
这里定义了一个结构体 Stack
,它包含一个整数 top
用于指示栈顶位置,以及一个字符数组 items
作为栈的存储空间。
initStack
: 初始化栈,将 top
设置为 -1
表示栈为空。isEmpty
: 检查栈是否为空。isFull
: 检查栈是否已满。push
: 入栈操作,如果栈未满,将元素压入栈顶。pop
: 出栈操作,如果栈非空,弹出并返回栈顶元素。peek
: 查看栈顶元素,但不移除。int precedence(char op) {
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}int isOperator(char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}
precedence
: 返回运算符的优先级,+
和 -
优先级较低(返回1),*
和 /
优先级较高(返回2),其他情况返回0。isOperator
: 判断字符是否为运算符。void infixToPostfix(char* infix, char* postfix) {
Stack s;
initStack(&s);
int k = 0;for (int i = 0; infix[i] != '\0'; i++) {
if (isdigit(infix[i])) {
while (isdigit(infix[i])) {
postfix[k++] = infix[i++];
}
postfix[k++] = ' '; // 添加空格作为后缀表达式元素的分隔符
i--; // 退回到数字的最后一个字符
} else if (infix[i] == '(') {
push(&s, infix[i]);
} else if (infix[i] == ')') {
while (!isEmpty(&s) && peek(&s) != '(') {
postfix[k++] = pop(&s);
postfix[k++] = ' ';
}
pop(&s); // 弹出 '('
} else if (isOperator(infix[i])) {
while (!isEmpty(&s) && precedence(peek(&s)) >= precedence(infix[i])) {
postfix[k++] = pop(&s);
postfix[k++] = ' ';
}
push(&s, infix[i]);
}
}// 将栈中剩余的运算符弹出并添加到后缀表达式中
while (!isEmpty(&s)) {
postfix[k++] = pop(&s);
postfix[k++] = ' ';
}
postfix[k-1] = '\0'; // 移除最后一个空格,并添加字符串结束符
}
infixToPostfix
: 将中缀表达式转换为后缀表达式。遍历中缀表达式,根据操作数、运算符和括号进行处理,并使用栈来管理运算符的顺序。int evaluatePostfix(char* postfix) {
Stack s;
initStack(&s);
int i = 0;
while (postfix[i] != '\0') {
if (isdigit(postfix[i])) {
int num = 0;
while (isdigit(postfix[i])) {//这段代码用于解析并提取后缀表达式(即逆波兰表达式)中的数字
num = num * 10 + (postfix[i++] - '0');}
push(&s, num);
} else if (isOperator(postfix[i])) {
int val2 = pop(&s);
int val1 = pop(&s);
switch (postfix[i]) {
case '+': push(&s, val1 + val2); break;
case '-': push(&s, val1 - val2); break;
case '*': push(&s, val1 * val2); break;
case '/': push(&s, val1 / val2); break;
}
i++;
} else {
i++; // 跳过空格
}
}
return pop(&s); // 返回最终的计算结果
}
isdigit(postfix[i])
:
isdigit
是一个标准库函数,用于检查给定字符是否为数字字符('0' 到 '9')。如果 postfix[i]
是数字字符,则返回非零值,否则返回零。postfix[i]
是当前正在处理的字符。num = num * 10 + (postfix[i++] - '0');
:
num
是用来存储最终解析出的整数的变量。postfix[i++] - '0'
:
postfix[i]
是当前的数字字符。'0'
将字符转换为对应的整数值。例如,字符 '7'
减去 '0'
的 ASCII 值等于整数 7。i++
是后置递增操作,表示在使用 postfix[i]
之后,再将 i
增加 1,以便指向下一个字符。num = num * 10 + ...
:
num
是 12,现在读取到一个新的数字字符 '3',那么计算 num = 12 * 10 + 3
结果为 123。evaluatePostfix
: 对后缀表达式进行求值。遍历后缀表达式,遇到操作数则压入栈中,遇到运算符则弹出栈顶的两个操作数进行运算,并将结果压回栈中,直到表达式结束。int main() {
char infix[MAX], postfix[MAX];
printf("Enter an infix expression: ");
fgets(infix, MAX, stdin);
infix[strcspn(infix, "\n")] = '\0'; // 去除末尾的换行符infixToPostfix(infix, postfix);
printf("Postfix expression: %s\n", postfix);int result = evaluatePostfix(postfix);
printf("Result: %d\n", result);return 0;
}
infixToPostfix
转换为后缀表达式,然后调用 evaluatePostfix
计算结果并输出。这些代码组合在一起实现了一个基本的表达式求值器,仅可以处理加减乘除四则运算和括号。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。