从键盘读入一个合法的算术表达式,输出正确的结果;显示输入序列和栈的变化过程,操作数类型扩充到实数。 "(3.14159/2+sqrt(1/3^2+4)+1/2^2ln(1/1.1(2+sqrt(1/3^2+4))))*23.45@"; 选作内容:扩充运算符集合;引入变量操作数; 核心存储结构:栈。,c语言代码,含main函数
时间: 2023-11-17 18:08:21 浏览: 127
以下是利用算符优先法求算术表达式值的C语言代码,支持实数和扩充的运算符集合:
```c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define MAX_STACK_SIZE 100 // 栈的最大容量
#define MAX_EXPRESSION_SIZE 100 // 算术表达式的最大长度
// 定义运算符的优先级
enum precedence { lparen, rparen, plus, minus, times, divide, mod, power, log, sqrtfunc, eos, operand, variable };
// 利用算符优先法求算术表达式的值
double eval(char expr[]);
// 将字符转换为对应的运算符优先级
int get_token(char symbol);
// 判断栈是否为空
int is_empty(int top);
// 判断栈是否已满
int is_full(int top);
double variables[26] = {0}; // 存储变量的值
int main() {
char expr[MAX_EXPRESSION_SIZE];
printf("请输入算术表达式(以@结尾):\n");
scanf("%s", expr);
printf("算术表达式的值为:%lf\n", eval(expr));
return 0;
}
double eval(char expr[]) {
double op1, op2, result, token, n = 0;
int top = 0; // 栈的指针
int stack[MAX_STACK_SIZE]; // 创建一个栈
stack[0] = eos; // 栈底设置为eos
token = get_token(expr[n++]); // 获取表达式中的第一个字符
while (token != eos) {
if (token == operand) { // 如果是操作数,直接入栈
char num_str[MAX_EXPRESSION_SIZE];
int i = 0;
num_str[i++] = expr[n-1]; // 将第一个字符存入字符串中
while (isdigit(expr[n]) || expr[n] == '.') { // 继续扫描操作数
num_str[i++] = expr[n++];
}
num_str[i] = '\0'; // 字符串结尾
stack[++top] = operand; // 入栈标志
double num = atof(num_str);
stack[++top] = *(int*)# // 将浮点数转换为整数后入栈
}
else if (token == variable) { // 如果是变量,入栈变量的值
stack[++top] = operand; // 入栈标志
stack[++top] = variables[expr[n-1]-'a']; // 将变量的值入栈
}
else { // 如果是运算符
int op = token;
if (op == log) { // 如果是对数函数
stack[++top] = log; // 入栈标志
token = get_token(expr[n++]); // 继续获取下一个字符
if (token != lparen) { // 判断对数函数是否有左括号
printf("语法错误:缺少左括号\n");
exit(1);
}
stack[++top] = lparen; // 入栈左括号
}
while (get_token(stack[top]) >= op) { // 如果栈顶元素优先级不低于当前运算符,就弹出栈顶元素并计算
int op_top = stack[top--];
if (op_top == sqrtfunc) { // 如果是平方根函数
op2 = *(double*)&stack[top--];
result = sqrt(op2); // 计算平方根
stack[++top] = *(int*)&result; // 将计算结果入栈
}
else if (op_top == log) { // 如果是对数函数
op2 = *(double*)&stack[top--];
op1 = *(double*)&stack[top--];
if (op1 <= 0 || op2 <= 0 || op1 == 1) { // 判断对数函数的参数是否合法
printf("错误:对数函数参数不合法\n");
exit(1);
}
result = log(op2)/log(op1); // 计算对数函数
stack[++top] = *(int*)&result; // 将计算结果入栈
}
else { // 如果是普通运算符
op2 = *(double*)&stack[top--];
op1 = *(double*)&stack[top--];
switch (op_top) {
case plus:
result = op1 + op2;
break;
case minus:
result = op1 - op2;
break;
case times:
result = op1 * op2;
break;
case divide:
if (op2 == 0) { // 判断除数是否为0
printf("错误:除数不能为0\n");
exit(1);
}
result = op1 / op2;
break;
case mod:
if (op2 == 0) { // 判断模数是否为0
printf("错误:模数不能为0\n");
exit(1);
}
result = fmod(op1, op2); // 计算模运算
break;
case power:
result = pow(op1, op2); // 计算幂运算
break;
}
stack[++top] = *(int*)&result; // 将计算结果入栈
}
}
if (op == rparen) { // 如果是右括号,弹出左括号
while (get_token(stack[top]) != lparen) { // 查找左括号
top--;
}
top--;
}
else { // 如果是其他运算符,直接入栈
stack[++top] = op;
}
}
token = get_token(expr[n++]); // 继续获取下一个字符
}
return *(double*)&stack[top]; // 返回栈顶元素,即表达式的值
}
int get_token(char symbol) {
switch (symbol) {
case '(':
return lparen;
case ')':
return rparen;
case '+':
return plus;
case '-':
return minus;
case '*':
return times;
case '/':
return divide;
case '%':
return mod;
case '^':
return power;
case 'l':
return log;
case 's':
return sqrtfunc;
case '@':
return eos;
default:
if (symbol >= '0' && symbol <= '9' || symbol == '.') {
return operand;
}
else if (symbol >= 'a' && symbol <= 'z') {
return variable;
}
else {
printf("错误:无法识别的字符 %c\n", symbol);
exit(1);
}
}
}
int is_empty(int top) {
return top == 0;
}
int is_full(int top) {
return top == MAX_STACK_SIZE - 1;
}
```
以上代码中,除了支持实数和扩充的运算符集合外,还支持变量操作数。在`eval`函数中,增加了对变量的处理,使用`variables`数组存储变量的值。在`get_token`函数中,增加了对变量的判断,如果是变量就返回`variable`标志。在计算对数函数和平方根函数时,需要将参数从栈中取出,并进行相应的计算。
阅读全文