#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define inf float(0x3f3f3f3f)
#define MAXSIZE 100
char priority[7] = {'+', '-', '*', '/', '(', ')', '#'};
char priority_relationship[7][7] = {
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', ' '},
{'>', '>', '>', '>', ' ', '>', '>'},
{'<', '<', '<', '<', '<', ' ', '='}
}; // 各个运算符之间的优先级关系
int get_index(char str[])
{// 获取相应运算符的索引
for(int i = 0; i < 7; i++)
{
if(str[0] == priority[i]) return i;
}
printf("未找到匹配的字符\n");
}
char Precede(char inside_data[], char input_data[])
{// 获取两个运算符之间的优先级关系
int inside_index = get_index(inside_data);
int input_index = get_index(input_data);
return priority_relationship[inside_index][input_index];
}
typedef struct StackNode
{
char data[MAXSIZE]; // 压入栈里面的数据都是字符型,在进行运行时,记得将字符型数字转换为浮点型数字
struct StackNode *next;
}StackNode, *LinkStack;
void InitStack(LinkStack &S)
{// 构造一个空栈S,栈顶指针置空
S = NULL;
}
void Push(LinkStack &S, char data[])
{// 在栈顶插入元素data
StackNode *p;
p = (StackNode *)malloc(sizeof(StackNode)); // 生成新的结点
strcpy(p->data, data); // 将新结点的数据域置为data
p->next = S; // 将新结点插入栈顶
S = p; // 修改栈顶指针为p
}
char *Pop(LinkStack &S)
{// 删除S的栈顶元素, 用data返回其值
char data[MAXSIZE];
if(S == NULL) printf("错误!!!\n栈为空, 无法执行删除命令...");
else
{
StackNode *p;
strcpy(data, S->data); // 将栈顶元素赋给data
p = S; // 用p临时保存栈顶元素的空间,以备释放
S = S->next; //修改栈顶指针
free(p); // 释放原栈顶元素的空间
return data;
}
}
char *GetTop(LinkStack &S)
{// 获取栈顶元素
if(S != NULL)
return S->data;
else
{
printf("错误!!!\n栈顶为空");
return "0";
}
}
float str_to_float(char *str)
{// 将字符串数据转换成浮点型数据
float num = 0;
int state_1 = 0; // 用于判断是否读取到小数点的状态值, 0代表还没有读取到
int state_2 = 0; //用于判断是否读取到负号的状态值, 0代表还没有读取到
while(( *str != '\0' && *str >= '0' && *str <= '9') || *str == '.' || (*str == '-' && *(str + 1) != '\0'))
{// 注意判断小数点和负号
if(*str == '.') state_1 = 1; // 当读取到小数点的时候, 状态值state_1赋值为1
else if(*str == '-') state_2 = 1; // 当读取到负号的时候, 状态值state_2赋值为1
else
{
if(state_1 == 0) num = num * 10 + (*str - '0');
else
{
num += (*str - '0') * pow(0.1, state_1);
state_1++;
}
}
str++;
}
if(*str != '\0') return inf;
else if(state_2 == 1)
{
return num * -1;
}
else return num;
}
char *float_to_str(float num)
{// 将浮点型数据装换成字符串数据,保留浮点型数据小数点后4位的值
char str[MAXSIZE];
sprintf(str, "%.4f", num); // 保留小数点后4位
return str;
}
float Operate(char a[], char theta[], char b[])
{//执行运算
float a_num = str_to_float(a);
float b_num = str_to_float(b);
if(theta[0] == '+') return a_num + b_num;
else if(theta[0] == '-') return a_num - b_num;
else if(theta[0] == '*') return a_num * b_num;
else if(theta[0] == '/') return a_num / b_num;
else printf("错误!!!\n无该运算符");
}
void EvaluateExpression()
{
StackNode *OPND, *OPTR;
char str[MAXSIZE];
char theta[MAXSIZE];
char a[MAXSIZE];
char b[MAXSIZE];
InitStack(OPND); // 初始化栈 OPND
InitStack(OPTR); // 初始化栈 OPTR
Push(OPTR, "#"); // 将 "#" 压入栈OPTR
printf("请输入算术表达式(支持负数,浮点型数据),每个值用空格隔开输入,并以#结束\n");
scanf("%s", str);
while(str[0] != '#' || GetTop(OPTR)[0] != '#')
{
if(str_to_float(str) != inf)
{ // 如果str不是运算符,则压入OPND栈,读取下一个字符串str
Push(OPND, str); // 将字符串str压入OPTR栈
scanf("%s", str); // 读入下一个字符串str
}
else
{ // 如果字符串str是运算符,使用 Precede() 函数获取OPTR栈顶元素的运算符和字符串str的运算符的优先级
switch (Precede(GetTop(OPTR), str)) // 使用 Precede() 函数获取相应优先级
{
case '<':
Push(OPTR, str); // 将字符串str压入OPTR栈
scanf("%s", str); // 读入下一个字符串str
break;
case '>':
strcpy(theta, Pop(OPTR)); // 弹出OPTR栈顶的运算符字符串并赋值给变量 theta
strcpy(b, Pop(OPND)); // 弹出OPND栈顶的数值字符串并赋值给变量 b
strcpy(a, Pop(OPND)); // 弹出OPND栈顶的数值字符串并赋值给变量 a
char temp_str[MAXSIZE];
strcpy(temp_str, float_to_str(Operate(a, theta, b))); // 根据相应的三个字符串进行运算,把结果赋给temp_str
Push(OPND, temp_str); // 将运算结果 temp_str 压入OPND栈
break;
case '=':
Pop(OPTR); // 弹出OPTR栈顶的运算符字符串
scanf("%s", str); // 读入下一个字符串str
break;
default:
printf("错误!!!\n该优先级不存在!!!");
}
}
}
printf("%s\n", GetTop(OPND));
}
int main(void)
{
EvaluateExpression();
system("pause");
return 0;
}
浮点数表代式求值
最新推荐文章于 2024-09-13 15:16:05 发布
本文探讨了C++编程中如何实现一个计算器,处理带有运算符和括号的算术表达式,通过栈和优先级规则来解析和计算。涉及str_to_float函数、Precede函数和Operate函数,展示了如何处理不同运算符的结合性和优先级。
摘要由CSDN通过智能技术生成